分析这道题,我们可以得出,假如a,b,c三只虫子,a和b可以交配,b和c也可以交配,那么a和c一定是同行,因为他们和同一个异性交配了。所以我们可以把关系抽象成图,在ab之间,bc之间各连一条线长度为1,那么路径长度为双数的两个点一定是同性,单数则为异性。仔细考虑我们不难发现,这是因为性别只有两种,跨越性别单数次称之为异性,跨越性别双数次称之为同性。
然后我们可以采用建图的方法,顺理成章的就想到了并查集,带权并查集。两个点之间路径长度模2的剩余系,1代表异性,0代表同性,在同一个并查集中出现矛盾冲突后,我们就可以输出答案。
下面上代码:
1 //perfect; 2 #include<iostream> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cmath> 6 #include<cstring> 7 #include<string> 8 #include<queue> 9 #include<algorithm> 10 using namespace std; 11 const int MAXN=2005; 12 int father[MAXN],d[MAXN]; 13 int n,m,k,w,t,s,cnt=0,ans=0; 14 void take() 15 { 16 memset(father,0,sizeof(father)); 17 for(int i=1;i<=n;i++) father[i]=i; 18 memset(d,0,sizeof(d)); 19 ans=0; 20 } 21 int get(int x) 22 { 23 if(x==father[x]) return x; 24 int rt=father[x]; 25 father[x]=get(father[x]); 26 d[x]=(d[x]+d[rt]+2)%2; 27 return father[x]; 28 } 29 int main() 30 { 31 scanf("%d",&t); 32 while(t--){ 33 scanf("%d%d",&n,&m); 34 take(); 35 for(int i=1;i<=m;i++){ 36 int x,y; 37 scanf("%d%d",&x,&y); 38 int fx=get(x),fy=get(y); 39 if(fx!=fy){ 40 father[fx]=fy; 41 d[fx]=(1-d[x]+d[y]+2)%2; 42 } 43 else{ 44 if((d[x]+d[fx]-d[y]+2)%2==1) continue; 45 else ans=1; 46 } 47 } 48 cnt++; 49 printf("Scenario #%d:\n",cnt); 50 if(ans) puts("Suspicious bugs found!"); 51 else puts("No suspicious bugs found!"); 52 puts(""); 53 } 54 return 0; 55 }