BZOJ4423 Bytehattan
Description
比特哈顿镇有n*n个格点,形成了一个网格图。一开始整张图是完整的。
有k次操作,每次会删掉图中的一条边(u,v),你需要回答在删除这条边之后u和v是否仍然连通。
Input
第一行包含两个正整数n,k(2<=n<=1500,1<=k<=2n(n-1)),表示网格图的大小以及操作的个数。
接下来k行,每行包含两条信息,每条信息包含两个正整数a,b(1<=a,b<=n)以及一个字符c(c=N或者E)。
如果c=N,表示删除(a,b)到(a,b+1)这条边;如果c=E,表示删除(a,b)到(a+1,b)这条边。
数据进行了加密,对于每个操作,如果上一个询问回答为TAK或者这是第一个操作,那么只考虑第一条信息,否则只考虑第二条信息。
数据保证每条边最多被删除一次。
Output
输出k行,对于每个询问,如果仍然连通,输出TAK,否则输出NIE。
Sample Input
3 4
2 1 E 1 2 N
2 1 N 1 1 N
3 1 N 2 1 N
2 2 N 1 1 N
2 1 E 1 2 N
2 1 N 1 1 N
3 1 N 2 1 N
2 2 N 1 1 N
Sample Output
TAK
TAK
NIE
NIE
TAK
NIE
NIE
转化为对偶图,边界外的点算作S
删边就相当于在两个对偶点上连边,判断两点是否连通就相当于判断两个对偶点是否形成环
因为不会删重复的边,所以用并查集判断是否出现环
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 int set[3000001],n,k,cnt,id[1501][1501],ans; 8 char s[11],ss[11]; 9 int find(int x) 10 { 11 if (set[x]!=x) set[x]=find(set[x]); 12 return set[x]; 13 } 14 int main() 15 {int i,j,x,y,xx,yy,p,q; 16 cin>>n>>k; 17 cnt=1; 18 for (i=1;i<n;i++) 19 { 20 for (j=1;j<n;j++) 21 { 22 id[i][j]=++cnt; 23 } 24 } 25 for (i=1;i<=cnt;i++) 26 set[i]=i; 27 ans=1; 28 for (i=1;i<=k;i++) 29 { 30 scanf("%d%d %s",&x,&y,s); 31 scanf("%d%d",&xx,&yy); 32 if (ans==0) scanf("%s",s),x=xx,y=yy; 33 else scanf("%s",ss); 34 if (s[0]=='E') 35 { 36 if (y==1) p=find(1),q=find(id[x][1]); 37 if (y==n) p=find(1),q=find(id[x][n-1]); 38 if (y!=1&&y!=n) p=find(id[x][y-1]),q=find(id[x][y]); 39 } 40 else 41 { 42 if (x==1) p=find(1),q=find(id[1][y]); 43 if (x==n) p=find(1),q=find(id[n-1][y]); 44 if (x!=1&&x!=n) p=find(id[x][y]),q=find(id[x-1][y]); 45 } 46 if (p!=q) ans=1,set[p]=q; 47 else ans=0; 48 if (ans==0) printf("NIE\n"); 49 else printf("TAK\n"); 50 } 51 }