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

posted @ 2012-08-12 12:35  pushing my way  阅读(302)  评论(0编辑  收藏  举报