题意:有n个人,彼此间是朋友或敌对关系。有4种操作:1设置a,b为朋友 2设置a,b为敌对 3询问a,b是不是朋友 4询问a,b是不是敌对。对于询问操作,如果是输出1,否则输出0。对于设置操作,如果与已知关系矛盾,输出-1,操作无效;有效的设置不输出。
思路:有相互关系的并查集。如果已知两个人的关系,不管是朋友还是敌对,就放到一个集合里。用一个数组表示元素与父元素间的关系。不管是查找和合并都涉及到关系数组的改变,写的时候头脑一定要清醒,了解它是怎么运作的。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <ctype.h>
#define INF 1000000
using namespace std;
int fa[10010];
bool rel[10010];
int find(int i){
if(i==fa[i])return i;
int t=fa[i];
fa[i]=find(fa[i]);
rel[i]=!(rel[i]^rel[t]);
return fa[i];
}
void uni(int a,int b,bool f){
int t=find(a);
fa[find(a)]=find(b);
rel[t]=!(!(rel[a]^rel[b])^f);
find(a);
find(b);
}
int main(){
int n;
while(cin>>n){
for(int i=0;i<=n;i++){
fa[i]=i;
}
for(int i=0;i<=n;i++){
rel[i]=1;
}
int c,x,y;
while(cin>>c>>x>>y){
if(!(c||x||y))break;
switch(c){
case 1:
if(find(x)!=find(y)){
uni(x,y,true);
}else if(rel[x]!=rel[y]){
cout<<"-1"<<endl;
}
break;
case 2:
if(find(x)!=find(y)){
uni(x,y,false);
}else if(rel[x]==rel[y]){
cout<<"-1"<<endl;
}
break;
case 3:
if(find(x)==find(y)){
if(rel[x]==rel[y]){
cout<<"1"<<endl;
}else{
cout<<"0"<<endl;
}
}else{
cout<<"0"<<endl;
}
break;
case 4:
if(find(x)==find(y)){
if(rel[x]==rel[y]){
cout<<"0"<<endl;
}else{
cout<<"1"<<endl;
}
}else{
cout<<"0"<<endl;
}
break;
}
}
}
return 0;
}
428

被折叠的 条评论
为什么被折叠?



