题目来源:http://ac.nbutoj.com/Problem/view.xhtml?id=1187
题意:就是说有一个方阵,然后对小方阵操作,也就是标记小方阵,求最后标记的方阵中能连到一起的方阵最大是多少。能连到一起的条件是至少有一条公共边。
思路:由于有多次询问,每次询问都要输出,做多询问200000次,因此朴素方法的话,肯定会tle。由此想到并查集,对小方阵标记时,查看该小方阵的四周是否有标记的,若有标记的,则用并查集合并到一个集合里面即可。
代码:
#include <iostream> #include <cstdio> #include <string.h> #include <string> using namespace std; #define CLR(arr,val) memset(arr,val,sizeof(arr)) const int N = 1001000; int father[N],num[N],flag[N],mmax; int find(int x){ int fx = father[x]; if(fx == x) return father[x]; else{ father[x] = find(father[x]); return father[x]; } } void Unionset(int dit,int value){ int fdit = find(dit); int fvalue = find(value); if(fdit != fvalue){ father[fvalue] = fdit; num[fdit] += num[fvalue]; if(num[fdit] > mmax) mmax = num[fdit]; } return; } int main(){ //freopen("1.txt","r",stdin); int n,ask; while(scanf("%d",&n) != EOF){ scanf("%d",&ask); char ss[3]; for(int i = 0;i < n*n;++i){ father[i] = i; num[i] = 1; } int x,y,up,down,left,right,dit,isnot = 0; CLR(flag,0); mmax = 0; while(ask--){ scanf("%s",ss); if(ss[0] == 'B'){ isnot = 1; scanf("%d%d",&x,&y); if(x == 0) dit = y; else dit = x*n+y; flag[dit] = 1; if(x != n-1 && flag[dit+n]) Unionset(dit,dit+n); if(x != 0 && flag[dit-n]) Unionset(dit,dit-n); if(y != 0 && flag[dit-1]) Unionset(dit,dit-1); if(y != n-1 && flag[dit+1]) Unionset(dit,dit+1); } else{ if(mmax == 0 && isnot == 1) printf("1\n"); else printf("%d\n",mmax); } } } return 0; }