题意:已知某昆虫有雄雌两性,然后给出案例数t, 对应每一个案例中给出编号数目和关系数目n,m ,在接下来m行中给出对应关系为异性的a b,最后判断所给中关系中是否有冲突部分
思路:关于种类并查集,有两种思路
(1) 开对应集合数量倍空间,类似POJ-1703也是两个互斥关系的集合:
有n个成员,开两倍空间(即假设某个成员有两面的属性),1~n为一组, n+1~2n为一组。a与b互斥,则a与b反(即b+n)为同一集合,同时b与a反(a+n)为同一集合,这样就确立联系.同时在union操作中,我们引入rank(相当于模拟某个作为根的结点“高度”,高度越高意味着他作为根连接的其他结点越多,用于在合并的时候进行确立结点连接关系
(2)通过在压缩路径中确立之间的关系,即在Unoin和find中要增加 关系式的转换 也可以参考POJ-1182 食物链(三种集合关系),大部分题解是通过路径压缩关系式确立之间的关系.
这里我采用第一种,思路上比较简单。其中判断是否冲突是通过在每一次条件确立中,如果关系已知,且与当前输入的关系矛盾,则设标志变量flag 为false即关系冲突
然后注意输出格式要多输出一行空白
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 const int maxn = 1e5+7; 6 using namespace std; 7 8 int pre[2*maxn]; 9 int rank[2*maxn]; 10 int find(int x) 11 { 12 if (x == pre[x]) return x; 13 else return pre[x] = find(pre[x]); 14 } 15 16 void unite(int x, int y) 17 { 18 int px = find(x), py = find(y); 19 if (px == py) return ; 20 else if (rank[px] > rank[py]) 21 { 22 pre[py] = px; 23 } 24 else 25 { 26 pre[px] = py; 27 if (rank[px] == rank[py]) rank[py]++; 28 } 29 } 30 31 bool same(int x, int y) 32 { 33 int px = find(x), py = find(y); 34 return px == py; 35 } 36 int main() 37 { 38 int T, n, m,cnt; 39 scanf("%d", &T); 40 cnt= 0; 41 while(T--) 42 { 43 bool flag = true; 44 scanf("%d%d", &n, &m); 45 for (int i = 1;i <= 2*n; i++) 46 { 47 pre[i] = i; 48 rank[i] = 1; 49 } 50 int a, b; 51 for (int i = 0; i < m; i++) 52 { 53 scanf("%d%d", &a, &b); 54 //以确定关系 55 if ( same(a, b) || same(a, b+n) ) 56 { 57 if ( same(a, b) ) flag = false; 58 //是异性则符合条件继续 59 else continue; 60 } 61 //未确定关系 62 else 63 { 64 unite(a, b+n); 65 unite(a+n, b); 66 } 67 } 68 printf("Scenario #%d: ",++cnt); 69 if(!flag) printf("Suspicious bugs found! "); 70 else printf("No suspicious bugs found! "); 71 } 72 return 0; 73 }