题意:一组昆虫性别有公有母,现给出一组交配信息,问是否有同性恋发生。
思路:1、并查集。维护一个性别数组。关键代码见注释!
2、二分图着色判断是否为二分图。也就是在交配的虫子之间连边,判断每一个连通分量是否为二分图。
#include <stdio.h> #include <string.h> #define N 2005 int f[N],gender[N]; int c,n,m,T; int find(int x){ int temp = f[x]; if(f[x] == x) return x; f[x] = find(f[x]); gender[x] = gender[x] ^ gender[temp];//根据父节点的性别是否变化更新自己的(也就是一条链顶端节点性别变化,后边的跟着变化) return f[x]; } int main(){ freopen("a.txt","r",stdin); scanf("%d",&T); for(c = 1;c<=T;c++){ int i,j,x,y,xx,yy,flag = 0; scanf("%d %d",&n,&m); for(i = 1;i<=n;i++) f[i] = i; memset(gender,0,sizeof(gender)); for(i = 0;i<m;i++){ scanf("%d %d",&x,&y); if(flag) continue; xx = find(x); yy = find(y); if(xx == yy){ if(gender[x] == gender[y]) flag = 1; }else{ f[xx] = yy; if(gender[x] == gender[y])//如果xy当前性别相同,那么改变xx的性别值,这是因为与x有关的所有性别均需发生改变(注意:yy可以看成根,它的性别值始终为0) gender[xx] = 1; } } printf("Scenario #%d:\n",c); if(flag) printf("Suspicious bugs found!\n\n"); else printf("No suspicious bugs found!\n\n"); } return 0; }
二分图着色:
#include <stdio.h> #include <string.h> #define N 2005 struct edge{ int y,next; }e[1000005*2]; int first[N],flag[N];//flag是着色信息 int n,m,top,res,T,c; void add(int x,int y){ e[top].y = y; e[top].next = first[x]; first[x] = top++; } void dfs(int x,int fa){ int i,y,color; color = 1-flag[x];//0和1分别表示两种颜色 for(i = first[x];i!=-1;i=e[i].next){ y = e[i].y; if(y!=fa){ if(flag[y]==-1){ flag[y] = color; dfs(y,x);//深搜着色 } else if(flag[y]!=color){//如果此次着色和其原有颜色不同,则说明不是二分图 res = 0; return; } } } } int main(){ freopen("a.txt","r",stdin); scanf("%d",&T); for(c = 1;c<=T;c++){ int i,x,y; top = 0; res = 1; memset(flag,-1,sizeof(flag)); memset(first,-1,sizeof(first)); scanf("%d %d",&n,&m); for(i = 0;i<m;i++){ scanf("%d %d",&x,&y); add(x,y); add(y,x); } for(i = 1;res && i<=n;i++){ if(-1 == flag[i]){ flag[i] = 0; dfs(i,0); } } printf("Scenario #%d:\n",c); if(!res) printf("Suspicious bugs found!\n\n"); else printf("No suspicious bugs found!\n\n"); } return 0; }