poj 1182

http://poj.org/problem?id=1182

一个利用并查集的经典题目。

思路:在网上看到别人的思路,觉得方法还是挺不错的。

首先,开辟一个3*n的数组belg,用来存b和c的关系,在belg[c+m]存,c是被谁吃的,belg[c+2*m]存b是吃谁的。

bool judge(int x,int y) {return (Find(x)==Find(y));}

如果judge(b,c+m)和 judge(b,c+2*m)都为假的话,那么可以说明,b和c是在同类。

然后合并b,c。b+m,c+m。b+2m,c+2m。

第一个judge可以判断,b不会吃c,第二个Judge可以判断c也不会吃b,所以,b,c肯定是同类。

如果judge(b,c)和judge(b,c+2*m)都为假的话,那么可以说明,c是被b吃的,然后合并b,c+m。b+m,c+2*m。b+*2m,c;

第一个judge可以判断b和c不是同一类,第二个judge可以判断c不会吃b,那么就可以说明c是被b吃的。c是被b吃的,那么说明,c+m存的就是b,所以c+m和b合并。之后的也是同样的意思。

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 
 5 int belg[150005];
 6 
 7 int Find(int x)   //Find 的迭代写法。
 8 {
 9     int _x=x,_b;
10     while(_x!=belg[_x])
11     {
12         _x=belg[_x];
13     }
14     while(x!=belg[x])
15     {
16         _b=belg[x];
17         belg[x]=_x;
18         x=_b;
19     }
20     return _x;
21 }
22 
23 bool judge(int x,int y) {return (Find(x)==Find(y));}
24 
25 void unite(int x,int y)
26 {
27     int root1=Find(x);
28     int root2=Find(y);
29     if(root1!=root2) belg[root1]=root2;
30 }
31 
32 int main()
33 {
34     int m,n,a,b,c,ans=0;
35   //  freopen("in.txt","r",stdin);
36     scanf("%d%d",&m,&n);
37     for(int i=1;i<=m*3;i++)
38         belg[i]=i;
39     while(n--)
40     {
41         scanf("%d%d%d",&a,&b,&c);
42         if(b>m||c>m) ans++;
43         else if(a==1)
44         {
45             if(judge(b,c+m)||judge(b,c+2*m)) ans++;
46             else {     //b,c是同类时,合并所有的信息。
47                 unite(b,c);   
48                 unite(b+m,c+m);
49                 unite(b+2*m,c+2*m);
50             }
51         }
52         else {
53             if(judge(b,c)||judge(b,c+2*m)) ans++;
54             else {     //b,c不是同类时,合并那些是同类的信息。
55                 unite(b,c+m);
56                 unite(b+m,c+2*m);
57                 unite(b+2*m,c);
58             }
59         }
60     }
61     printf("%d\n",ans);
62     return 0;
63 }

 

posted @ 2016-07-27 09:50  一个_小菜鸟  阅读(258)  评论(0编辑  收藏  举报