题目地址:http://poj.org/problem?id=1703
题目大意:警察抓了n个坏蛋,这些坏蛋分别属于龙帮或蛇帮。输入m个语句,A x y询问x和y的关系(在一个帮派,不在,不能确定),D x y表示x和y不在一个帮派。
思路:种类并查集。维护一个数组rel[x]表示x和根节点的关系(0表示在一个帮派,1表示不在),初始全为0(自己和自己在一个帮派),更新rel用偏移量(rel[x]表示px->x,D x y表示x->y=1)。由于2要特判,输入里分三类:1.n==2&&opr=='A' 2.opr=='D' 3.其他【由于至少有两个帮派的人,当n==2是两个人一定分别是两个帮派的,输出为different】【初始化时记得n从1到n】
1 #include <cstdio> 2 3 using namespace std; 4 5 const int N = 100000+5; 6 int fa[N], rel[N]; 7 8 void init(int n) 9 { 10 for(int i = 0; i <= n; i++) 11 { 12 fa[i] = i; 13 rel[i] = 0; 14 } 15 } 16 17 //注意下查找时更新rel[]里那个px 18 int found(int x) 19 { 20 if(fa[x] == x) 21 return x; 22 int px = fa[x]; 23 fa[x] = found(fa[x]); 24 rel[x] = (rel[px]+rel[x])%2; 25 return fa[x]; 26 } 27 28 void unite(int x, int y) 29 { 30 int px = found(x); 31 int py = found(y); 32 if(px != py) 33 { 34 fa[py] = px; 35 rel[py] = (rel[x]+1+2-rel[y])%2; 36 } 37 } 38 39 int main() 40 { 41 int n, m, t, a, b; 42 char opr; 43 scanf("%d", &t); 44 while(t--) 45 { 46 scanf("%d%d", &n, &m); 47 init(n); 48 for(int i = 0; i < m; i++) 49 { 50 getchar(); 51 scanf("%c%d%d", &opr, &a, &b); 52 if(n == 2 && opr =='A')//2要特判。分类一共是A2、其他A、D 53 { 54 printf("In different gangs.\n"); 55 } 56 else if(opr == 'D') 57 unite(a, b); 58 else 59 { 60 int pa = found(a); 61 int pb = found(b); 62 if(pa != pb) 63 printf("Not sure yet.\n"); 64 else if(rel[a] == rel[b]) 65 printf("In the same gang.\n"); 66 else 67 printf("In different gangs.\n"); 68 } 69 } 70 } 71 return 0; 72 }
【特判2wa了好久!!!!!!!!!!!!!!!!!!!初始化函数也写错了。。刚开始写成<n了!!!!!!!!!!!】