题意:
有n个人,属于两个敌对的帮派;
O a b代表ab是敌对的;
S a b输出a,b的关系(一个帮派,不同帮派或不确定);
思路:
r[a] 代表a和它父亲的关系;0为同帮,1为不同帮;
如果两个不再一个集合里,则就是不确定关系;
如果两个在同一个集合,就要判断他们和父亲的关系(同一个父亲)
如果两个人都和父亲是敌对.或者都是友好,则两人是友好;
否则敌对;需要在find和Union的时候维护r数组;
#include<cstdio>
#include<cstring>
const int N = 50005;
int p[N],r[N],n,k;
void init(int x) {
for(int i = 0; i <= x; i++) {
p[i] = i;
r[i] = 0;
}
}
int find_set(int x) {
if(x != p[x]) {
int fx = find_set(p[x]);
r[x] = (r[x] + r[p[x]]) % 3;
p[x] = fx;
}
return p[x];
}
bool Union(int x,int y,int rela) {
int px = find_set(x);
int py = find_set(y);
if(px == py) {
if(((r[y] - r[x] + 3) % 3) != rela)
return true;
else
return false;
}
p[py] = px;
r[py] = (r[x] - r[y] + rela + 3) % 3;
return false;
}
int main() {
int sum = 0;
scanf("%d%d",&n,&k);
init(n);
for(int i = 0; i < k; i++) {
int tmp,x,y;
scanf("%d%d%d",&tmp,&x,&y);
if(x > n|| y > n || (x == y && tmp == 2))
sum++;
else if(Union(x,y,tmp - 1))
sum++;
}
printf("%d\n",sum);
}