POJ 1703

题目链接:http://poj.org/problem?id=1703

题目大意:两组犯罪团体,抓住N个人,他们属于且唯一属于两组犯罪团体之一。然后,给你M条信息,也分两类。D类信息说明id0和id1是不同组织的,A类信息是询问id0和id1的关系,包括不同组织,相同组织和无法判断。


解题思路:

       并查集,但简单并查集思路与该题目不符合。因为简单并查集会告诉你两个目标是相同组织的,此题恰好相反。但是,两人属于不同组织说明他们是有联系的,也就是说1D2, 2D3,那么1和3的关系是可以推断出来的,也就可以将1,2,3理解为一个集合(暂且叫做不等集合,里面包含许多不等关系,这些不等关系可以推出相等关系)。

       那么D信息表明id0所属的集合与id1所属的集合应该是同一个不等集合的(合并)。然而,在并查集中,不等集合都需要一个根作为代表。这里谁做根都可以,但是必须让根的父节点等于根,C2G[x]=x。 这里可能会有疑问:不是不等集合吗?那么C2G[i]和i的关系到是什么?

       C2G[i] 表示i的根,但是在不等集合里是无法确定C2G[i]与i的组织关系。因此,另外用rank记录i,rank[i]表示i和C2G[i]的组织关系,0代表相同,1代表不同。

#include<stdio.h>

const int MAX_N = 100001;
int C2G[MAX_N];
int Rank[MAX_N];
int T, N, M;

void init(){

	for(int i = 1; i <= N; i++){
		C2G[i] = i;
		Rank[i] = 0;
	}
	return;
}

int Find(int x){
	if( x == C2G[x] ){
		Rank[x] = 0;
		return x;
	}

	int fx = Find(C2G[x]);
	Rank[x] = (Rank[x] + Rank[C2G[x]]) % 2;
	C2G[x] = fx;
	
	return C2G[x];
}

void Union(int x, int y){
	int fx = Find(x);
	int fy = Find(y);

	if( fx == fy ){
		return ;
	}
	else{
		C2G[fx] = fy;
		Rank[fx] = (Rank[x] + Rank[y] + 1) % 2;
	}

	return;
}

int main(){

	scanf("%d", &T);
	for(int i = 0; i < T; i++){
		scanf("%d%d", &N, &M);
		
		init();
		char str;
		int id0, id1;

		for(int j = 0; j < M; j++){
			scanf("\n%c%d%d", &str, &id0, &id1);
			if( str == 'A' ){
				int FatherId0 = Find(id0);
				int FatherId1 = Find(id1);
				if( FatherId0 == FatherId1 ){
					if( Rank[id0] == Rank[id1] ){
						printf("In the same gang.\n");
					}
					else{
						printf("In different gangs.\n");
					}
				}
				else{
					printf("Not sure yet.\n");
				}
			}
			else{
				Union(id0, id1);
			}
		}
	}

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值