标签:
题意:有一个科学家提出了一个假设,一种虫子只有异性恋,而不是同性恋,然后开始实验来验证猜想,给出了n个虫子,编号从1到n,给出了q组恋爱虫子的编号,问是否验证猜想。
题解:数组倍增,给每个虫子一个异性恋的对象集合,然后每次输入的两个虫子如果不在同一个集合内,就放到对方异性恋集合内,否则无法验证猜想。
#include <stdio.h>
const int N = 4005;
int n, q, pa[N];
int get_parent(int x) {
return x == pa[x] ? x : pa[x] = get_parent(pa[x]);
}
int main() {
int t, cas = 1;
scanf("%d", &t);
while (t--) {
scanf("%d%d", &n, &q);
int nn = 2 * n;
for (int i = 1; i <= nn; i++)
pa[i] = i;
int flag = 0;
while (q--) {
int a, b;
scanf("%d%d", &a, &b);
int px = get_parent(a);
int py = get_parent(b);
if (px == py)
flag = 1;
else {
int t1 = get_parent(a + n);
int t2 = get_parent(b + n);
pa[px] = t2;
pa[py] = t1;
}
}
if (cas > 1)
printf("\n");
printf("Scenario #%d:\n", cas++);
if (flag)
printf("Suspicious bugs found!\n");
else
printf("No suspicious bugs found!\n");
}
return 0;
}
另一种做法,带权并查集,加一个数组rel[i]表示i和父节点是否是同性,寻找根节点时更新rel[i],如果发现输入的两个虫子是同一个根节点且与根节点关系相同,这两个虫子是同性恋,否则放到一个集合内,并更新其中一个虫子的根节点的rel。
#include <stdio.h>
const int N = 4005;
int n, q, pa[N], rel[N];
int get_parent(int x, int &r) {
int temp = x;
r = 1;
while (x != pa[x]) {
if (rel[x] == 0)
r = !r;
x = pa[x];
}
pa[temp] = x;
rel[temp] = r;
return pa[x];
}
int main() {
int t, cas = 1;
scanf("%d", &t);
while (t--) {
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; i++) {
pa[i] = i;
rel[i] = 1;
}
int flag = 0;
while (q--) {
int a, b, r1, r2;
scanf("%d%d", &a, &b);
int px = get_parent(a, r1);
int py = get_parent(b, r2);
if (px == py && r1 == r2)
flag = 1;
else {
pa[py] = px;
rel[py] = r1 == r2 ? 0 : 1;
}
}
if (cas > 1)
printf("\n");
printf("Scenario #%d:\n", cas++);
if (flag)
printf("Suspicious bugs found!\n");
else
printf("No suspicious bugs found!\n");
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/hyczms/article/details/45440825