UVa 10227 - Forests

题目:有P个人和T棵树。现在给你某个人听到某棵树倒下声音的一些二元组,如果两个人听到的树的集合相同他们就是同一集合,问人分成几个集合。

分析:并查集。因为数据量很小(100)所以直接暴力判断是否相同即可,然后利用并查集处理合并,最后查询并查集中根(sets(i) = i)的个数即是结果。

注意:memset在<string>中;恶心的输入格式。

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>

using namespace std;

//union_set  
int  sets[205];  
int  sums[205];  
int  rank[205];  
//初始化
void Union_set( int a, int b )
{
	for ( int i = a ; i <= b ; ++ i ) {
		sets[i] = i;
		sums[i] = 1;
		rank[i] = 0;
	}
} 
//返回根节点   
int  Find( int a )  
{  
    if ( a != sets[a] )  
        sets[a] = Find( sets[a] );  
    return sets[a];  
}  
//合并集合   
void Union( int a, int b )  
{  
    if ( rank[a] < rank[b] ) {  
        sets[a]  = b;  
        sums[b] += sums[a];  
    }else {  
        if ( rank[a] == rank[b] )  
            rank[a] ++;  
        sets[b]  = a;  
        sums[a] += sums[b];  
    }  
}  
//union_set end 

int P_T[101][101];

//判断相统集合 
int same( int p1, int p2, int t )
{
	for ( int i = 1 ; i <= t ; ++ i )
		if ( P_T[p1][i] != P_T[p2][i] )
			return 0;
	return 1;
}

int main()
{
	int n,t,p,T,P,a,b;
	while ( ~scanf("%d",&n) ) {
		getchar();getchar();
		for ( int k = 0 ; k < n ; ++ k ) {
			if ( k > 0 ) printf("\n");
			scanf("%d%d",&P,&T);
			getchar();
			Union_set( 1, P+T );
			memset( P_T, 0, sizeof(P_T) );
			while ( 1 ) {
				char c = getchar();
				ungetc(c,stdin);
				if ( c == '\n' || c == EOF ) break;
				scanf("%d%d",&p,&t);
				getchar();
				P_T[p][t] = 1;
			}
			
			//合并集合 
			for ( int i = 1 ; i <= P ; ++ i )
				for ( int j = i+1 ; j <= P ; ++ j ) {
					a = Find( i );
					b = Find( j );
					if ( a != b && same( a, b, T ) )
						Union( a, b );
				}
			
			//查询集合的个数 
			int sum = 0;
			for ( int i = 1 ; i <= P ; ++ i )
				sum += (i == Find(i));
			printf("%d\n",sum);
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值