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