POJ-1182 分组并查集

今天刚发现,之前做的并查集只是贴模板基本就能过,题意改变一点,自己还是不懂,其实我还没入门呢。。。

题意:食物链,A吃B,B吃C,C吃A,输入m组数据:

1 a b:a 和 b 是同一类

2 a b:a吃b

判断这m组数据有几句是假话。

假话条件:

1)在2的情况下,a == b;

2)a > n || b > n;

3)和前面的语句冲突;

思路:推荐一篇好的博客:http://cavenkaka.iteye.com/category/217940

其实在这里才明白Rank[]数组的意义,表示的是x 和 p[x] 的关系;博客挺详细的,学到不少,看下一步用不用得上了。。。

 1 #include <iostream>
 2 #include <cmath>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <string>
 7 #include <sstream>
 8 #include <algorithm>
 9 #define Max 2147483647
10 #define INF 0x7fffffff
11 #define N 50010
12 #define ll long long
13 #define mem(a,b) memset(a,b,sizeof(a))
14 #define repu(i, a, b) for(int i = (a); i < (b); i++)
15 const double PI=-acos(-1.0);
16 using namespace std;
17 int rank[N],p[N];
18 void init(int n)
19 {
20     repu(i,1,n+1)
21     {
22         rank[i] = 0;
23         p[i] = i;
24     }
25 }
26 int find_set(int x)
27 {
28     if(x!=p[x])
29     {
30         int fx=find_set(p[x]);
31         rank[x]=(rank[x]+rank[p[x]])%3; //注意 是rank[p[x]]而不是rank[fx]
32         p[x]=fx;
33     }
34     return p[x];
35 }
36 bool Union(int x,int y,int d)
37 {
38     int u = find_set(x);
39     int v = find_set(y);
40     printf("%d---%d\n",u,v);
41     if(u == v)///如果在同一个集合
42     {
43         if((3 - rank[x] + rank[y])%3!=d)///如果符合吃鱼的关系
44             return true; ///这个关系可以通过举例得出
45         else
46             return false;
47     }
48     p[v] = u ;
49     rank[v]=(rank[x]-rank[y]+d+3)%3;///与上式不同 需仔细归纳
50     return false;
51 }
52 int main()
53 {
54     int n,m;
55     scanf("%d%d",&n,&m);
56     init(n);
57     int sum = 0,a,b,d;
58     repu(i,0,m)
59     {
60         scanf("%d%d%d",&d,&a,&b);
61         if((a == b&&d == 2) || a > n || b > n)
62             sum++;
63         else if(Union(a,b,d-1))  ///传d-1 方便关系式的表达
64             sum++;
65     }
66     printf("%d\n",sum);
67 }
View Code
posted @ 2015-05-27 23:56  一麻袋码的玛侬  阅读(202)  评论(0编辑  收藏  举报