非常基础的一道在查询时需要传递其它信息的并查集,
这方面的经典题目首推 POJ 1182 食物链
鉴于博客里没有这种类型的题目就放上来了。
写合并的时候还错误的把两个节点间的距离写成两个根节点之间的距离了,
智商捉急得简直不能多说 = =|||
题目链接:http://poj.org/problem?id=1703
题意:
有一些人分属两个帮派。
每个帮派至少有一个人。
给出两种操作:
1)D X Y 说明X和Y不属于一个部落
2)A X Y 询问X和Y是否在一个部落,或者不能确定
算法:
对每个节点维护一个到父根节点的“距离”,
若距离为奇数代表不在一个部落,
距离为偶数代表在同一个部落
然后对于同一个集合内的节点显然这是一个等价关系。
trick:每个帮派至少有一个人。所以n=2时必定不属于同一个部落
代码如下:
#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define eps 1e-8
const int MAXN=110000;
int p[MAXN],dis[MAXN];
int findp(int x) {
if(p[x]==-1) {
return x;
}
int px=findp(p[x]);
dis[x]+=dis[p[x]];
dis[x]&=1;
return p[x]=px;
}
int main() {
int cas;
scanf("%d",&cas);
while(cas--) {
int n,m;
scanf("%d%d",&n,&m);
memset(p,-1,sizeof(p));
memset(dis,0,sizeof(dis));
while(m--) {
char ch;
int x,y;
getchar();
scanf("%c%d%d",&ch,&x,&y);
x--;
y--;
if(ch=='D') {
int px=findp(x);
int py=findp(y);
if(px!=py) {
p[px]=py;
dis[px]=(1+dis[x]+dis[y])&1;
}
} else {
int px=findp(x);
int py=findp(y);
if(n==2) {
puts("In different gangs.");
} else if(px!=py) {
puts("Not sure yet.");
} else {
if(((dis[x]+dis[y])&1)) {
puts("In different gangs.");
} else {
puts("In the same gang.");
}
}
}
}
}
return 0;
}