poj2492_bfs_并查集
题意:
给的就是n个虫子 m对虫子发生过关系 然后问有没有虫子是同性恋。
分析:题目等价为,n个点,m条边,能否仅用两种颜色染完所有点,并使每条边的两个点不同色。
bfs,遍历每个顶点,如果相邻顶点染有相同的颜色,说明有同性恋!
代码:
View Code
1 #include <iostream> 2 #include <stdio.h> 3 #include <memory.h> 4 #include <queue> 5 using namespace std; 6 const int maxnum=2001; 7 bool array[maxnum][maxnum]; 8 bool use[maxnum]; 9 bool color[maxnum]; 10 int m,n; 11 bool flag; 12 queue<int> q; 13 14 void Init() 15 { 16 int i; 17 int a,b; 18 scanf("%d%d",&m,&n); 19 memset(array,false,sizeof(array)); 20 memset(use,false,sizeof(use)); 21 for(i=1;i<=n;i++) 22 { 23 scanf("%d%d",&a,&b); 24 array[a][b]=true; 25 array[b][a]=true; 26 } 27 flag=true; 28 29 while(!q.empty()) 30 q.pop(); 31 } 32 33 void bfs(int u) 34 { 35 int v,i; 36 use[u]=true; 37 color[u]=true; 38 q.push(u); 39 while(!q.empty()) 40 { 41 v=q.front(); 42 q.pop(); 43 for(i=1;i<=m;i++) 44 if(i!=v && array[v][i]) 45 { 46 if(!use[i]) 47 { 48 color[i]=!color[v]; 49 use[i]=true; 50 q.push(i); 51 } 52 else 53 { 54 if(color[i]==color[v]) 55 { 56 flag=false; 57 return ; 58 } 59 } 60 } 61 } 62 } 63 64 int main() 65 { 66 int num; 67 scanf("%d",&num); 68 int i,k; 69 for(k=1;k<=num;k++) 70 { 71 Init(); 72 for(i=1;i<=m;i++) 73 if(!use[i] && flag) 74 bfs(i); 75 76 printf("Scenario #%d:\n",k); 77 if(!flag) 78 printf("Suspicious bugs found!\n\n"); 79 else 80 printf("No suspicious bugs found!\n\n"); 81 } 82 return 0; 83 }
网上有用并查集的,小小的学习了一下。内存比bfs小的多。
并查集思想:
1.用father[i]表示i的根节点,sex[i]表示与它的根节点相比,true表示性别相同,false表示性别不同
2.对于每对a,b。查找father[a]和father[b],不同进行组合,相同进行判断。
3.在a,b的根节点不同的情况下,需要更新sex[father[a]]和sex[fathe[b]]。
首先求出a,b相对于根节点的sex[a]和sex[b].举例
输入1 2后有。father[2]=1,sex[2]=false;
输入2 3 后:首先得出father[2]=1,father[3]=3,不同。
更新father:father[3]=1
更新sex:
因为根节点1和3相对自己是同性,而2相对于1是异性,所以,这样sex[2]^sex[3]=不同两项异或,为1,
所以sex[3]=true;这样3就与1同性。
代码:
View Code
1 #include <iostream> 2 #include <stdio.h> 3 using namespace std; 4 const int maxnum=2001; 5 int root[maxnum]; 6 int sex[maxnum];//相对于父节点的性别,true表示是同性,false表示异性 7 int m,n; 8 bool flag; 9 10 void Init() 11 { 12 scanf("%d%d",&m,&n); 13 int i; 14 for(i=1;i<=m;i++) 15 { 16 root[i]=i; 17 sex[i]=true; 18 } 19 flag=true; 20 } 21 22 int find(int i) 23 { 24 int t=i; 25 bool f=true; 26 while(t!=root[t]) 27 { 28 if(!sex[t]) //sex[t]==false; 29 f=!f; 30 t=root[t]; 31 } 32 root[i]=t; //状态压缩 33 sex[i]=f; //当前节点相对于根节点的性别 34 return root[i]; 35 } 36 37 void function() 38 { 39 int i; 40 int a,b; 41 int ra,rb; 42 for(i=1;i<=n;i++) 43 { 44 scanf("%d%d",&a,&b); 45 if(flag) 46 { 47 ra=find(a); 48 rb=find(b); 49 if(ra==rb) 50 { 51 if(sex[a]==sex[b]) //找到同性恋 52 flag=false; 53 } 54 else 55 { 56 root[rb]=ra; //合并两个集合 57 sex[rb]=sex[a]^sex[b]; //更新sex[rb] 58 } 59 } 60 } 61 } 62 63 int main() 64 { 65 int num; 66 int k; 67 scanf("%d",&num); 68 for(k=1;k<=num;k++) 69 { 70 Init(); 71 function(); 72 printf("Scenario #%d:\n",k); 73 if(!flag) 74 printf("Suspicious bugs found!\n\n"); 75 else 76 printf("No suspicious bugs found!\n\n"); 77 } 78 return 0; 79 }
tjuoj 1706