题型:数据结构
题意:
有n个齿轮,4种操作:
L a b : 将a和b齿轮放在一起,两个齿轮放在一起,则属于一个集合,且转动方向相反。
Q a b : 查询a和b的转动方向是否相同,答案为Same、Different、Unknown
D a : 将a齿轮从集合中拿出来
S a : 查询a齿轮所在的集合中的元素个数
分析:
初始化根节点权值为0。
L a b时,将a和b加入一个集合,且b比a的权值大1。
Q a b时,若a和b的权值差为奇数,则方向相反,否则方向相同。 不在一个几个就无法查询。
D a时,由于被删除的节点的信息以后还会用到,所以就新建一个点作为该点拿出去。
S a时,直接查询a的祖先节点上储存的集合元素个数。
代码:
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#define M 612345
using namespace std;
int n,m;
int father[M],r[M],num[M];
int ts[M];
void init() {
for(int i=1; i<=n+m; i++) {
father[i] = -1;
r[i] = 0;
num[i] = 1;
ts[i] = i;
}
}
int Find(int x) {
if(father[x] == -1) return x;
int tmp = Find(father[x]);
r[x] = (r[x] + r[father[x]]) % 2;
father[x] = tmp;
return father[x];
}
void Union(int x,int y) {
int rootx=Find(x);
int rooty=Find(y);
if(rootx != rooty){
r[rootx] = (r[y] - r[x] + 1) % 2;
father[rootx] = rooty;
num[rooty] += num[rootx];
}
}
int main() {
while(~scanf("%d%d",&n,&m)) {
init();
char str[10];
int a,b;
int now = n+1;
while(m--) {
scanf("%s",str);
if(str[0] == 'L') {
scanf("%d%d",&a,&b);
Union(ts[a],ts[b]);
continue;
}
if(str[0] == 'D') {
scanf("%d",&a);
num[Find(ts[a])]--;
ts[a] = now++;
continue;
}
if(str[0] == 'Q') {
scanf("%d%d",&a,&b);
if(Find(ts[a]) == Find(ts[b])) {
if(r[ts[a]] == r[ts[b]]) {
puts("Same");
} else {
puts("Different");
}
} else {
puts("Unknown");
}
continue;
}
if(str[0] == 'S') {
scanf("%d",&a);
printf("%d\n",num[Find(ts[a])]);
continue;
}
}
}
return 0;
}