题目大意:题目好长,就不细说了
解题思路:解法1:设置两个数组,一个数组是并查集的基本数组p[maxn],另一个数组r[maxn]表示点和根节点的关系,0表示和根节点是朋友,1表示和根结点是敌人,那么在并查集的时候就可以顺便设置以下r数组了,这里用到的是向量思想,什么是向量思想,下面会给链接,这里就不解释了
解法2:给每个人设置一个永远的敌人,他和他永远的敌人不在同一个集合,然后只要结合这四个点进行判断即可
解法1代码:
#include<stdio.h>
#include<string.h>
#define MAXN 10010
int N, p[MAXN], delta[MAXN];
int find(int x)
{
if(p[x] == x)
return x;
int tx = find(p[x]);
delta[x] =(delta[x] + delta[p[x]]) % 2;
p[x] = tx;
return tx;
}
void init()
{
int i, x, y, tx, ty, flag;
for(i = 0; i < N; i ++)
{
p[i] = i;
delta[i] = 0;
}
for(;;)
{
scanf("%d%d%d", &flag, &x, &y);
if(!x && !y && !flag)
break;
tx = find(x);
ty = find(y);
if(flag == 3)
{
if(tx != ty || delta[x] != delta[y])
printf("0\n");
else
printf("1\n");
}
else if(flag == 4)
{
if(tx != ty || delta[x] == delta[y])
printf("0\n");
else
printf("1\n");
}
else if(flag == 1)
{
if(tx == ty)
{
if(delta[x] != delta[y])
printf("-1\n");
}
else
{
p[tx] = ty;
delta[tx] = (delta[x] - delta[y] + 2) % 2;
}
}
else if(flag == 2)
{
if(tx == ty)
{
if(delta[x] == delta[y])
printf("-1\n");
}
else
{
p[tx] = ty;
delta[tx] = (delta[x] - delta[y] + 1) % 2;
}
}
}
}
int main()
{
while(scanf("%d", &N) == 1)
{
init();
}
return 0;
}
解法2代码:
#include<cstdio>
#include<cstring>
#define maxn 20020
int p[maxn],x1,x2,y1,y2,N;
int find(int x) {
return x == p[x] ? p[x]:p[x] = find(p[x]);
}
int main() {
scanf("%d",&N);
for(int i = 0; i <= 2 * N; i++)
p[i] = i;
int c,x,y;
while(scanf("%d%d%d",&c,&x,&y) != EOF && c + x + y) {
x1 = find(x); y1 = find(x + N);
x2 = find(y); y2 = find(y + N);
if(c == 1) {
//如果x和y的敌人是朋友
if(x1 == y2) {
printf("-1\n");
continue;
}
//如果x和y是朋友,那么x的敌人就是y的敌人的朋友,y的敌人就是x的敌人的朋友
p[x1] = x2; p[y1] = y2;
}
if(c == 2) {
//如果x和y是朋友
if(x1 == x2) {
printf("-1\n");
continue;
}
//如果x和y是敌人,那么x的敌人就是y的朋友,y的敌人就是x的朋友
p[x1] = y2;
p[x2] = y1;
}
if(c == 3) {
if(x1 == x2)
printf("1\n");
else
printf("0\n");
}
if(c == 4) {
if(x1 == y2)
printf("1\n");
else
printf("0\n");
}
}
return 0;
}