【2018.5.12】模拟赛之三-ssl2415 连通块【并查集】

正题


题目大意

在一个n*n的棋盘上进行m此操作。在一个格子上放一个黑或白的棋子。多个相连的同色棋子形成一个连通块,求每次操作后求连通块数。


解题思路

并查集表示连通,然后每次扩展,如果有同色的就连通,注意判断已经是同一个连通块的情况。


代码

#include<cstdio>
using namespace std;
int n,m,s,c,x,y,color[601][601],father[250001];
int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
int find(int x)
{return x==father[x]?x:find(father[x]);}
//找祖先
int number(int x,int y)
{return (x-1)*n+y;}//求号
bool unionn(int x,int y)
{
    int fa=find(x),fb=find(y);
    if (fa==fb) return 0;
    if (fa<fb) father[fb]=fa;
    else father[fa]=fb;
    return 1;
}//相连并放回是否已经在同一连通块
int main()
{
    //freopen("blocks.in","r",stdin);
    f//reopen("blocks.out","w",stdout);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n*n;i++) father[i]=i;
    s=0;
    for (int i=1;i<=m;i++)
    {
        scanf("%d %d %d",&c,&x,&y);
        c++;
        color[x][y]=c;//标记
        s++;//连通块增加
        for (int k=0;k<4;k++)
        {
            int zx=x+dx[k],zy=y+dy[k];
            if (zx>0&&zx<=n&&zy>0&&zy<=n&&color[x][y]==color[zx][zy])
            {
                if(unionn(number(x,y),number(zx,zy)))
                  s--;//合并(注意判断是否在同一连通块)
            }
        }
        printf("%d\n",s);
    }
}

对拍

随机数据与暴力

#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<string>
#include<iostream>
#include<map>
#define random(x) rand()%x+1
using namespace std;
int n,m,s,color[501][501],c,x,y,e[501][501];
bool f[501][501];
void bfs(int x,int y,int c,int w)
{
    if (x>n || y>n || x<1 || y<1 || color[x][y]>c || !color[x][y])
    return;
    if (f[x][y] || e[x][y]!=w) return;
    f[x][y]=true;
    bfs(x+1,y,c,w);
    bfs(x-1,y,c,w);
    bfs(x,y+1,c,w);
    bfs(x,y-1,c,w);
}
int main()
{
    freopen("blocks.in","w",stdout);
    srand((unsigned)time(0));
    n=random(500);m=random(n*n);
    printf("%d %d\n",n,m);
    for (int i=1;i<=m;i++)
    {
        c=random(2)-1;
        x=random(n);y=random(n);
        while (color[x][y])
        {x=random(n);y=random(n);}
        printf("%d %d %d\n",c,x,y);
        color[x][y]=i;
        e[x][y]=c;
    }
    fclose(stdout);
    freopen("blocks.ans","w",stdout);
    for (int k=1;k<=m;k++)
    {
        memset(f,0,sizeof(f));
        s=0;
        for (int i=1;i<=n;i++)
          for (int j=1;j<=n;j++)
            if (!f[i][j] && color[i][j]<=k && color[i][j])
            {
                bfs(i,j,k,e[i][j]);
                s++;
            }
        printf("%d\n",s);
    }
    fclose(stdout);
}

对拍

#include<cstdio>
#include<ctime>
#include<cstdlib>
#include<cstring>
using namespace std;
int main()
{
    for (int t=1;t<=100000;t++)
    {
        system("blocksdata.exe");
        double st=clock();
        system("blocks.exe");
        double ed=clock();
        if (system("fc blocks.out blocks.ans"))
        {
            printf("WA");
            return 0;
        }
        else
        printf("AC point:%d time:%.0lfms\n",t,ed-st);
    }
}

猜你喜欢

转载自blog.csdn.net/mr_wuyongcong/article/details/80290509
今日推荐