题目链接:http://poj.org/problem?id=1703
题目大意:给n个人,m次询问。A代表询问a, b之间的关系,D代表给出a, b属于不同的帮派。
我的想法:
太菜了,上课的时候没想到这种方法。
思路:
1.感觉有点像2-sat的思想,对于D给出的a, b两人属于不同帮派。我们就将a于b的对立点用并查集维护在一个集合中,也将b于a的对立点连通。
2.查询时,若a,b两人pre值相等则属于同一帮派。若a与b的对立点属于同一集合,或b与a的对立点属于同一集合,则说明a与b属于不同帮派。若上述都不成立则说明关系还未知。
3.对立点是虚构的,不能影响到原来的点。所以数据范围翻倍,x + n代表x的对立点。
注意:不能用 cin 输入,会超时。只能用scanf
1 #include<stdio.h> 2 const int maxn = 2e5 + 1e4; 3 4 int pre[maxn]; 5 6 int find(int x) 7 { 8 if(pre[x] == x) 9 return x; 10 else 11 { 12 int root = find(pre[x]); 13 pre[x] = root; 14 return pre[x]; 15 } 16 } 17 18 int main() 19 { 20 int T; 21 scanf("%d", &T); 22 while(T --) 23 { 24 int n, m; 25 scanf("%d%d", &n, &m); 26 getchar(); 27 for(int i = 1; i <= 2 * n; i ++) 28 { 29 pre[i] = i; 30 } 31 for(int i = 1; i <= m; i ++) 32 { 33 char ch; 34 int a, b; 35 scanf("%c%d%d", &ch, &a, &b); 36 if(ch == 'D') 37 { 38 int x = find(a), y = find(b); 39 int xx = find(a + n), yy = find(b + n); 40 if(x != yy) 41 pre[yy] = x; 42 if(y != xx) 43 pre[xx] = y; 44 } 45 if(ch == 'A') 46 { 47 int x = find(a), y = find(b); 48 int xx = find(a + n), yy = find(b + n); 49 if(x == y) 50 printf("In the same gang.\n"); 51 else if(x == yy || y == xx) 52 printf("In different gangs.\n"); 53 else 54 printf("Not sure yet.\n"); 55 } 56 getchar(); 57 } 58 } 59 return 0; 60 }