题意:给定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;
}