UVa10158 War

        题意:有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;
} 


你可能感兴趣的:(并查集,uva)