正题
题目大意
在一个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;}elseprintf("AC point:%d time:%.0lfms\n",t,ed-st);}
}