POJ 1703 : Find them, Catch them
有两大帮派,现在不知道每个人的帮派情况。有两种操作,D x y 表示x和y在不同帮派,A x y查询x和y的帮派情况。
如果在同一帮派,输出In the same gang.
如果不在同一帮派,输出In different gangs.
不确定帮派情况则输出Not sure yet.
这里是POJ 1182 食物链 的同类型题目。
这个时候维护1~N为A帮派,N+1~2*N为B帮派。
如果Find(x) == Find(y + N)则代表一个在A帮派,一个在B帮派。
如果Find(x) == Find(y)则代表在同一个帮派。
其余则不确定情况。
需要注意的是当n = 2 时,需要特别判断下。
代码
#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
const int MAXNUM = 2* (100000 + 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 t;
int n,m;
char c;
int p,q;
int p1 ,p2 ;
scanf("%d", &t);
while(t--){
scanf("%d %d", &n, &m);
make_set(n * 2);
for(int i = 0 ; i < m ; i++){
getchar();
scanf("%c %d %d", &c , &p, &q);
// 查询
if(c=='A'){
if(n == 2){
if(Find(p) == Find(q + n))
printf("In the same gang.\n");
else
printf("In different gangs.\n");
continue;
}
if(Find(p) == Find(q + n)){
printf("In different gangs.\n");
}else if(Find(p) == Find(q)){
printf("In the same gang.\n");
}else{
printf("Not sure yet.\n");
}
}else{
Union(p, q + n);
Union(p + n , q);
}
}
}
return 0;
}
代码
#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
const int MAXNUM = 2* (100000 + 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] + 2 + (d)) % 2;
}
int main(){
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
int t;
int n,m;
char c;
int p,q;
int p1 ,p2 ;
scanf("%d", &t);
while(t--){
scanf("%d %d", &n, &m);
make_set(n);
for(int i = 0 ; i < m ; i++){
getchar();
scanf("%c %d %d", &c , &p, &q);
// 查询
if(c=='A'){
if(n == 2){
if(r[p] == r[q])
printf("In the same gang.\n");
else
printf("In different gangs.\n");
continue;
}
if(Find(p) == Find(q)){
if(r[p] != r[q]){
printf("In different gangs.\n");
}else{
printf("In the same gang.\n");
}
}else{
printf("Not sure yet.\n");
}
}else{
Union(p, q, 1);
}
}
}
return 0;
}