POJ 2492 : A Bug’s Life
编号1~n的Bugs,给出不同性别的m对,证明是否有同性恋的Bugs。
可以看出题目是含有关系的并查集,将1~n归为男性,n+1~2 * n为女性。
当查询Find(x) == Find(y)时,证明含有错误的列表,则输出Suspicious bugs found!,
否则则合并x,y(Union(x,y + n),Union(x + n , y)操作)
代码
#include <iostream>
#include <cstdio>
#include <map>
#include <cmath>
using namespace std;
const int MAXNUM = 2 * (1000000 + 10);
int id[MAXNUM];
int Size[MAXNUM];
// 初始化
void make_set(int n){
for(int i = 1 ; i <= n ; i++){
id[i] = i;
Size[i] = 1;
}
}
// 查找父节点
int Find(int p) {
while (p != id[p]) {
// 路径压缩,会破坏掉当前节点的父节点的尺寸信息,因为压缩后,当前节点的父节点已经变了
id[p] = id[id[p]];
p = id[p];
}
return p;
}
// 合并 p ,q节点
void Union(int p, int q) {
int pRoot = Find(p);
int qRoot = Find(q);
if (pRoot == qRoot) {
return;
}
// 按秩进行合并
if (Size[pRoot] > Size[qRoot]) {
id[qRoot] = pRoot;
Size[pRoot] += Size[qRoot];
} else {
id[pRoot] = qRoot;
Size[qRoot] += Size[pRoot];
}
}
int main(){
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
int Case = 1;
int n, m ;
int p, q;
int t;
scanf("%d", &t);
while(t--){
bool ans = true;
scanf("%d %d", &n, &m);
make_set(n * 2);
for(int i = 0 ; i < m ; i++){
scanf("%d %d", &p, &q);
if(Find(p) == Find(q))
ans = false;
else{
Union(p, q + n);
Union(p + n, q);
}
}
printf("Scenario #%d:\n",Case++);
if(ans)
printf("No suspicious bugs found!\n\n");
else
printf("Suspicious bugs found!\n\n");
}
return 0;
}
代码
#include <iostream>
#include <cstdio>
#include <map>
#include <cmath>
using namespace std;
const int MAXNUM = 1000000 + 10;
int id[MAXNUM];
int Size[MAXNUM];
int r[MAXNUM];
// 初始化
void make_set(int n){
for(int i = 1 ; i <= n ; i++){
id[i] = i;
Size[i] = 1;
r[i] = 0;
}
}
// 查找父节点
int Find(int p) {
while (id[p] != id[id[p]]) { //如果q不是其所在子树的根节点的直接孩子
r[p] = (r[p] + r[id[p]] ) % 2;
id[p] = id[id[p]]; //对其父节点到其爷爷节点之间的路径进行压缩
}
return id[p];
}
// 合并 p ,q节点
void Union(int p, int q, int d) {
int pRoot = Find(p);
int qRoot = Find(q);
if (pRoot == qRoot) {
return;
}
id[qRoot] = pRoot;
r[qRoot] = (r[p] - r[q] + d) % 2;
}
int main(){
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
int Case = 1;
int n, m ;
int p, q;
int t;
scanf("%d", &t);
while(t--){
bool ans = true;
scanf("%d %d", &n, &m);
make_set(n);
for(int i = 0 ; i < m ; i++){
scanf("%d %d", &p, &q);
if(Find(p) == Find(q) && r[p] == r[q])
ans = false;
else{
Union(p, q , 1);
}
}
printf("Scenario #%d:\n",Case++);
if(ans)
printf("No suspicious bugs found!\n\n");
else
printf("Suspicious bugs found!\n\n");
}
return 0;
}