bzoj4423[AMPPZ2013]Bytehattan

bzoj4423[AMPPZ2013]Bytehattan

题意:

n*n的顶点图,一开始相邻顶点均有边相连,现在删掉k条边,希望知道每次删边后边的两个端点是否联通。n≤1500,k≤2*n*(n-1),边最多被删一次。

题解:

隐隐觉得是并查集,但不知道删边怎么表示。在膜拜了题解后明白原来可以转成对偶图(以格子和外框为节点),原图的删边就是新图的加边。每次新图加边时就判断是否会产生环,若会,说明原图的两个端点在删边后不连通。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define maxn 2000
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 using namespace std;
 7 
 8 int pos[maxn][maxn],fa[2*maxn*maxn],tot,n,k,x[2],y[2]; bool ans; char s[2][5];
 9 inline int read(){
10     char ch=getchar(); int f=1,x=0;
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
12     while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
13     return f*x;
14 }
15 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
16 int main(){
17     n=read(); k=read(); tot=0; inc(i,1,n-1)inc(j,1,n-1)pos[i][j]=++tot; inc(i,1,tot)fa[i]=i;
18     inc(i,1,k){
19         x[0]=read(),y[0]=read(); scanf("%s",s[0]); x[1]=read(),y[1]=read(); scanf("%s",s[1]);
20         if(s[ans][0]=='N'){
21             int a=find(pos[x[ans]-1][y[ans]]),b=find(pos[x[ans]][y[ans]]);
22             if(a==b)ans=1;else fa[a]=b,ans=0;
23         }
24         else{
25             int a=find(pos[x[ans]][y[ans]-1]),b=find(pos[x[ans]][y[ans]]);
26             if(a==b)ans=1;else fa[a]=b,ans=0;
27         }
28         if(!ans)puts("TAK");else puts("NIE");
29     }
30     return 0;
31 }

20160724

原文地址:https://www.cnblogs.com/YuanZiming/p/5701719.html