题意:罪犯有两个帮派,有两种命令,D a b,a,b表示罪犯的编号,这句话表示a和b来自不同的帮派。A a b,a,b表示罪犯的编号,这句话是问你a和b是否来自同一个帮派,可以有三种回答,“目前不确定“,”是“,”不是“。罪犯最多10^5个,命令最多10^5个。
解法:并查集基础题。用一个struct node表示每一个罪犯,node.f表示该罪犯的父亲节点,node.r表示该罪犯与父亲节点对应的罪犯的关系(0表示来自同一个帮派,1表示不同)。然后写find函数注意更新node.r就行。具体见代码吧。
Ps:另外,本题是POJ 1182的简化版,题解见POJ 1182 食物链。
tag:并查集
1 /* 2 * Author: Plumrain 3 * Created Time: 2013-11-26 09:19 4 * File Name: G-POJ-1703.cpp 5 */ 6 #include <iostream> 7 #include <cstdio> 8 9 using namespace std; 10 11 const int maxn = 100005; 12 13 struct node{ 14 int f, r; 15 }; 16 17 char s[10]; 18 int n, m; 19 node a[maxn]; 20 21 void init() 22 { 23 for (int i = 0; i < n; ++ i){ 24 a[i].f = i; 25 a[i].r = 0; 26 } 27 } 28 29 int find(int x) 30 { 31 if (x == a[x].f){ 32 a[x].r = 0; 33 return x; 34 } 35 36 int y = a[x].f; 37 a[x].f = find(a[x].f); 38 a[x].r = (a[y].r + a[x].r) % 2; 39 return a[x].f; 40 } 41 42 void merge(int x, int y) 43 { 44 int t1 = find(x), t2 = find(y); 45 a[t1].f = t2; 46 a[t1].r = (a[y].r + a[x].r + 1) % 2; 47 } 48 49 int main() 50 { 51 int T; 52 scanf ("%d", &T); 53 while (T --){ 54 scanf ("%d%d", &n, &m); 55 init(); 56 57 int x, y; 58 while (m --){ 59 scanf ("%s%d%d", s, &x, &y); 60 int t1 = find(x), t2 = find(y); 61 if (s[0] == 'D') 62 merge(x, y); 63 else{ 64 if (t1 != t2) 65 printf ("Not sure yet. "); 66 else{ 67 if (a[x].r == a[y].r) 68 printf ("In the same gang. "); 69 else 70 printf ("In different gangs. "); 71 } 72 } 73 } 74 } 75 return 0; 76 }