hdu1829/poj2492 A Bug's Life(二分图判定or并查集能否划分为两个集合)

题意:给定n个昆虫,m对异性关系,问是否存在同性恋。

思路:建无向图然后二分图判定200W条边可以过,但这题网上搜题解的时候搜到一个并查集的方法,很神奇,码住码住。

即用op数组记录自己的一个异性①,然后再遇到自己的异性②时将异性①、异性②合并到一个集合里去。如果没出现可能的冲突的话,就说明这一对关系不影响题意,即任意其一为任一性别,另一为相反性别即可。

核心:敌人的敌人是朋友呐QAQ

思路来源(转载自):https://blog.csdn.net/jchangbrave/article/details/52337682

主要部分:

bool judge(int a,int b)
{
   if(find(a)==find(b))return 0;
   if(!op[a]&&!op[b])op[a]=b,op[b]=a;
   else if(!op[a])op[a]=b,unite(a,op[b]);
   else if(!op[b])op[b]=a,unite(b,op[a]);
   else union_set(a,op[b]),union_set(b,op[a]);
   return 1;
}

完整代码:

#include<cstdio>
#include<cstring>
using namespace std;
 
const int Max=2005;
int p[Max];
int op[Max];
int rank[Max];
 
void make_set(int x)
{
	p[x]=x;
	rank[x]=0;
}
 
int find_set(int x)
{
	int r=x;
	while(r!=p[r]) {
		r=p[r];
	}
	return r;
}
 
void union_set(int x,int y)
{
	int fx=find_set(x);
	int fy=find_set(y);
	if(fx==fy) return;
	else {
		if(rank[fx]>rank[fy]) {
			p[fy]=fx;
		}
		else {
			p[fx]=fy;
			if(rank[fx]==rank[fy]) rank[fy]++;
		}
	}
}
 
int main()
{
	int T,num,casf,cas=0;scanf("%d",&T);
	while(T--) {
		bool judge=false;
		for(int i=0;i<=Max;i++) make_set(i);
		memset(op,0,sizeof(op));
		scanf("%d%d",&num,&casf);
		for(int i=0;i<casf;i++) {
			int a,b;scanf("%d%d",&a,&b);
			if(find_set(a)==find_set(b)) judge=true;
			if(op[a]==0&&op[b]==0) {
				op[a]=b;op[b]=a;
			}
			else if(op[a]==0) {
				op[a]=b;union_set(a,op[b]);
			}
			else if(op[b]==0) {
				op[b]=a;union_set(b,op[a]);
			}
			else{
				union_set(a,op[b]);
				union_set(b,op[a]);
			}
		}
		printf("Scenario #%d:\n",++cas);
		if(judge) printf("Suspicious bugs found!\n");
		else printf("No suspicious bugs found!\n");
		if(T) printf("\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Code92007/article/details/82729846
今日推荐