PAT 1034. Head of a Gang (30) 并查集

/*************************
题意:
并查集问题
要求出边长总量大于w,并且节点个数大于2的集合
/************************
求解思路和注意点:
用哈希来处理字符串与数组下标的绑定
注意点(坑点):
	1.每个集合的father是自己定义的,但是输出时,必须输出入度值最大的节点。
************************/

/***********************
笔记:

*********************/
#include<iostream>
#include<stdio.h>
#include<string>
#include<vector>
#include<queue>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<stack>
#include<map>
using namespace std;
#define M 10001
#define INF 0x7fffffff
struct user{
	string name;
	string pw;
};

map<string,int> name;
int father[M];


int weight[M];
int num[M];
int sumweight[M];
int maxweight[M];
int selectw[M];
string getname[M];

bool cmp(int a,int b){
	return getname[selectw[a]]<getname[selectw[b]];
}
int findfa(int kid){
	int fa=kid;
	if(father[kid] != kid){
		fa=findfa(father[kid]);
		father[kid]=fa;
	}
	return fa;
}


int main(){
	int n,maxw,i,w;
	string s1,s2;

	int k=0;
	cin>>n>>maxw;
	for(i=0;i<n;i++){
		father[i]=i;
		weight[i]=0;
		sumweight[i]=0;
		num[i] = 1;
	}

	int fa1,fa2;
	int n1,n2;
	for(i=0;i<n;i++){
		cin>>s1>>s2>>w;
		if(name.find(s1)==name.end()){
			getname[k]=s1;
			name[s1]=k++;
		}
		if(name.find(s2)==name.end()){
			getname[k]=s2;
			name[s2]=k++;
		}
		n1=name[s1];
		n2=name[s2];
		
		fa1=findfa(n1);
		fa2=findfa(n2);
		if(fa1!=fa2){
			father[fa1]=fa2;
			num[fa2] += num[fa1];
			num[fa1] = 0;
			sumweight[fa2] += sumweight[fa1];
		}
		sumweight[fa2] += w;
		weight[n1] += w;
		weight[n2] += w;
		if(maxweight[fa1] > maxweight[fa2]){
			maxweight[fa2]=maxweight[fa1];
			selectw[fa2]=selectw[fa1];
		}
		if(weight[n1] > maxweight[fa2]){
			maxweight[fa2]=weight[n1];
			selectw[fa2]=n1;
		}
		if(weight[n2] > maxweight[fa2]){
			maxweight[fa2]=weight[n2];
			selectw[fa2]=n2;
		}
	}

	vector<int> vfa;
	for(i=0;i<k;i++){
		if(father[i]==i && sumweight[i]>maxw && num[i]>2)
			vfa.push_back(i);
	}
	sort(vfa.begin(),vfa.end(),cmp);
	printf("%d\n",vfa.size());
	int fa,j;
	for(i=0;i<vfa.size();i++){
		fa=vfa[i];
		cout<<getname[selectw[fa]]<<" "<<num[fa]<<endl;
	}

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值