[HNOI2010]平面图判定(带权并查集)

将相交的线连边判断二分图即可。
注意带权并查集的 F i n d \rm{Find} Find不能随便用。

A C C o d e \rm{AC Code} ACCode

#include
#define maxn 10005
#define pii pair
#define mp make_pair
#define pb push_back
using namespace std;

int n,m,x[maxn],y[maxn],d[maxn],pe[maxn],F[maxn],dis[maxn];
int Find(int u){
     
	if(!F[u]) return u;
	int f = F[u];
	F[u] = Find(F[u]);
	dis[u] ^= dis[f];
	return F[u];
}
int main(){
     
	int T;
	for(scanf("%d",&T);T--;){
     
		scanf("%d%d",&n,&m);
		memset(F,0,sizeof F),memset(dis,0,sizeof dis);
		for(int i=1;i<=m;i++){
     
			scanf("%d%d",&x[i],&y[i]);
			if(x[i] > y[i]) swap(x[i],y[i]);
		}
		for(int i=1;i<=n;i++) scanf("%d",&d[i]),pe[d[i]]=i;
		if(m > 3 * n - 6){
      puts("NO");continue; }
		vector<int>p;
		for(int i=1;i<=m;i++){
     
			x[i] = pe[x[i]] , y[i] = pe[y[i]];
			if(x[i] > y[i]) swap(x[i],y[i]);
			if(y[i] != (x[i] % n + 1))
				p.pb(i);
		}
		int g = p.size();
		bool ERROR = 0;
		for(int i=0;i<g;i++)
			for(int j=0;j<g;j++)
				if(x[p[i]]<x[p[j]]&&x[p[j]]<y[p[i]]&&y[p[i]]<y[p[j]]){
     
					int a , b;
					if((a=Find(p[i])) != (b=Find(p[j]))){
     
						F[a] = b;
						dis[a] = dis[p[i]] ^ dis[p[j]] ^ 1;
					}
					else if(dis[p[i]] == dis[p[j]]) ERROR = 1;
				}
		if(ERROR) puts("NO");
		else puts("YES");
 	}
}

你可能感兴趣的:(带权并查集)