1. 程式人生 > 其它 >bzoj#4423-[AMPPZ2013]Bytehattan【並查集】

bzoj#4423-[AMPPZ2013]Bytehattan【並查集】

正題

題目連結:https://darkbzoj.tk/problem/4423


題目大意

給出一個\(n*n\)的網格圖,然後四聯通的點之間連線。每次刪掉一條邊求這條邊的兩個點是否連通。強制線上。

\(1\leq n\leq 1500,1\leq m\leq 2n(n-1)\)


解題思路

轉換成對偶圖之後就可以變成加邊判斷連通性的問題了。

一個很簡單的理解就是如果新的刪去的邊在對偶圖構成了一個環那麼就會被分成環內和環外了。

時間複雜度\(O(m\alpha(m))\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1600;
int n,k,fa[N*N];
int find(int x)
{return (fa[x]==x)?(x):(fa[x]=find(fa[x]));}
void Unionm(int x,int y){
	x=find(x);y=find(y);
	if(x==y)return;fa[x]=y;
} 
int main()
{
	scanf("%d%d",&n,&k);
	bool last=1;
	for(int i=1;i<=(n+1)*(n+1);i++)fa[i]=i;
	for(int i=1;i<=n;i++){
		Unionm(i,i+1);
		Unionm((i-1)*(n+1)+1,i*(n+1)+1);
		Unionm(n*(n+1)+i,n*(n+1)+i+1);
		Unionm((i-1)*(n+1)+n+1,i*(n+1)+n+1);
	}
	for(int i=1;i<=k;i++){
		int x1,x2,y1,y2,x,y,p,q;
		char op1[2],op2[2],op;
		scanf("%d%d%s",&x1,&y1,&op1);
		scanf("%d%d%s",&x2,&y2,&op2);
		if(last)x=x1,y=y1,op=op1[0];
		else x=x2,y=y2,op=op2[0];
		if(op=='N'){
			p=x*(n+1)+y+1;
			q=(x-1)*(n+1)+y+1;
			p=find(p);q=find(q);
			if(p!=q)last=1,puts("TAK");
			else last=0,puts("NIE");
		}
		else{
			p=x*(n+1)+y+1;
			q=x*(n+1)+y;
			p=find(p);q=find(q);
			if(p!=q)last=1,puts("TAK");
			else last=0,puts("NIE");
		}
		Unionm(p,q);
	}
	return 0;
}