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 }
人生就像心电图,想要一帆风顺,除非game-over