题意
教授提出猜想,所有虫子都是异性恋,给出交配情况,判断他的猜想是否正确(肯定不正确啊)
思路
这是一道并查集,没有错。但是呢,它是带有关系的并查集,显然可以用向量解决(同食物链那一题)。
但是这一题它的关系非常简单,杀鸡焉用牛刀,所以和POJ1703一样,可以手动处理虫子之间的关系逻辑,来解决这个问题。
也就是说,建立一个oppo数组,表示号与号性别不同,如果,说明此前尚未标记的对立点,那么就把此时的对立关系更新成。一共需要手写个逻辑。
最后POJ不能用万能头,切记。
solution
#include <cmath> #include <cstdio> typedef long long ll; const int N = 1e5 + 7; const ll mod = 1e9 + 7; int height[N]; int s[N]; int n; // point numers void init_set() { for (int i = 1; i <= n; ++i) s[i] = i, height[i] = 0; } int find_set(int x) { if (x != s[x]) s[x] = find_set(s[x]); //路径压缩 return s[x]; } int find_set_circle(int x) { int r = x; while (s[r] != r) r = s[r]; //找到根节点 s[x] = r; //把路径上的元素的集改为根节点 return r; } void union_set(int x, int y) { x = find_set(x); y = find_set(y); if (height[x] == height[y]) height[x] = height[x] + 1, s[y] = x; else if (height[x] < height[y]) s[x] = y; else s[y] = x; } int main() { int T; int m; scanf("%d", &T); for (int t = 1; t <= T; ++t) { scanf("%d%d", &n, &m); init_set(); int oppo[N] = {0}; int a, b; bool flag = 1; while (m--) { scanf("%d%d", &a, &b); if (!flag) continue; if (oppo[a] && !oppo[b]) { union_set(oppo[a], b), oppo[b] = a; } else if (oppo[b] && !oppo[a]) { union_set(oppo[b], a), oppo[a] = b; } else if (oppo[a] && oppo[b]) { if (find_set(a) == find_set(b)) flag = 0; union_set(oppo[a], b), union_set(oppo[b], a); } else if (!oppo[a] && !oppo[b]) { oppo[a] = b, oppo[b] = a; } } if (t != 1) printf("\n"); printf("Scenario #%d:\n", t); if (flag) printf("No suspicious bugs found!\n"); else printf("Suspicious bugs found!\n"); } return 0; }