POJ 1703 Find them, Catch them、POJ 1182 食物链(种类并查集)

题目链接

POJ 1703 Find them, Catch them
POJ 1182 食物链

POJ 1703 Find them, Catch them
题目大意:

一共只有两类对象,给定两个操作,其中D,[a],[b]表示a,b不同类,[A],a,b查询啊a,b目前的关系,如果不确定则输出Not sure yet.,如果确定不同类输出In different gangs.,如果确定同类输出In the same gang.

解题思路:

并查集,难点在于平时并查集维护的是同一类的对象,而现在需要维护不同类之间的关系。这里参考种类并查集的思想,平时我们开一个f[n]的数组表示1n个物体的祖先,现在将这 数组扩展到2*n。利用1–n表示1–n这个n个物体的祖先,利用n+1–2*n表示1–n这n个物体的敌人的祖先。这时候如果a,b不同类,那么a与b的敌人同类,b与a的敌人同类,所以直接merge(a,b+n)和merge(a+n,b)即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
const int N=100010;
int vis[N];
using namespace std;
int f[N*2];//构造 ,种类并查集1~n,本身,n+1~2*n 敌人 

int findroot(int x){
	if(f[x]==x) return x;
	return f[x]=findroot(f[x]);
}
int flag=0;
void merge(int a,int b){
	int t1=findroot(a);
	int t2=findroot(b);
	if(t1!=t2){
		f[t1]=t2;
	}
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		int n,m;
		scanf("%d %d",&n,&m);
		for(int i=1;i<=2*n;i++) f[i]=i;
		for(int i=1;i<=m;i++){
			getchar();
			char op;
			int a,b;
			scanf("%c %d %d",&op,&a,&b); 
			if(op=='D'){
				merge(a,b+n);
				merge(a+n,b);
			}
			else{
				if(findroot(a)==findroot(b)){
					printf("In the same gang.\n");
				}
				else if(findroot(a)==findroot(b+n)){
					printf("In different gangs.\n");
				}
				else{
					printf("Not sure yet.\n");
				}
			}
		}
	}
	return 0;
}
POJ 1182 食物链
题目大意:

有三种动物,A吃B,B吃C,C吃A,构成闭环。对于这三类对象,与之前类似,开一个f[3*n]的数组,维护本身,猎物,天敌之间的关系即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<set>
#include<queue>
#include<vector>
using namespace std;
const int N=50010;
int f[N*3];//1~n本身,n+1~2*n,猎物,2*n+1~3*n天敌 
int tot=0;

int findroot(int x){
	if(f[x]==x) return x;
	return f[x]=findroot(f[x]);
}
void merge(int x,int y){
	int a=findroot(x);
	int b=findroot(y);
	if(a!=b){
		f[a]=b;
	}
}
int main(){
	int n,k;
	scanf("%d %d",&n,&k);
	for(int i=1;i<=3*n;i++) f[i]=i;
	
	for(int i=1;i<=k;i++){
		int d,x,y;
		scanf("%d %d %d",&d,&x,&y);
		
		if(x>n||y>n){tot++;continue;}
		
		else if(d==1){
			if(findroot(x+n)==findroot(y)||findroot(x+n*2)==findroot(y)){tot++;continue;} 
			merge(x,y);merge(x+n,y+n);merge(x+2*n,y+2*n);
		}
		
		else if(d==2){
			if(x==y){tot++;continue;}
			
			if(findroot(x)==findroot(y)||findroot(x+n*2)==findroot(y)){tot++;continue;}
			merge(x+n,y);merge(x+n*2,y+n);merge(x,y+n*2); 
		}
		
	}
	printf("%d\n",tot);
	return 0;
}

posted @ 2019-08-08 09:44  xzhws  阅读(44)  评论(0编辑  收藏  举报