1034 Head of a Gang (仅得24分)

求连通分量

1.dfs

2.并查集

用并查集的时候,因为接下来可能还会更新通话分钟数u,我又不想把对应的一类存储再进行判断......所以就在合并时进行判断操作,寻找最大的点(pre) 实时更新  只需要确保更新完后后续的也一并压入即可。

4 5测试点没过  暂时不清楚哪里遇到问题了

#include<iostream>
#include<cstdio>
#include<map>
#include<vector>
#include<set>
#include<algorithm>

using namespace std;

const int N = 4000+5;
map<string, int> a;
string Nm[N];
int Sum[N];

int Tot[N];
int pre[N];
struct Node {
	string Head;
	int Total, Num;
	Node() {
		Head="";
		Total = 0;
		Num = 0;
	}

};
int cmp(Node a, Node b) {
	return a.Head < b.Head;
}
map<int, Node> ans;

int n, k, id = 1;
vector<Node> V;
bool flag[N];
set<string> S;
void init() {
	for(int i=0; i<=N; i++) {
		pre[i] = i;
		Tot[i] = 0;
		Sum[i] = 0;
		flag[i] = false;
	}
}
int Find(int x) {
	return x == pre[x] ? x : (pre[x] = Find(pre[x]));
}
bool Union(int a, int b) {

	if(Find(a) == Find(b)) { //不需要合并
		b = Find(b);
		if(Sum[a] > Sum[b]) {
			pre[b] = a;
			pre[a] = a;
			for(int i=0; i<id; i++)Find(i);
		}
		return false;
	} else {
		int ta = Find(a);
		int tb = Find(b);
		if(Sum[ta] < Sum[a]) {
			pre[a] = a;
			pre[ta] = a;
		}
		if(Sum[tb] < Sum[b]) {
			pre[b] = b;
			pre[tb] = b;
		}
		if(max(Sum[ta], Sum[a]) > max(Sum[tb], Sum[b])) {
			pre[b] = pre[a];
		} else
			pre[a] = pre[b];
		for(int i=0; i<id; i++)Find(i);

		return true;
	}
}
int main() {
	init();
	cin >> n >> k;

	string s1, s2;
	int tmp, cnt = n;

	for(int i=0; i<n; i++) {
		cin >> s1 >> s2 >> tmp;
		/*		S.insert(s1);
				S.insert(s2);
		*/
		if(a[s1] == 0) {
			Nm[id] = s1;
			a[s1] =  id++;
		}

		if(a[s2] == 0) {
			Nm[id] = s2;
			a[s2] =  id++;
		}
		Sum[a[s1]] += tmp;
		Sum[a[s2]] += tmp;

		if(Union(a[s1], a[s2])) {
			cnt --;
		}
	}
	 

	for(int i=1; i<id; i++) {
		tmp = pre[i];
		//	cout << pre[i] << ":" << Nm[]<< endl;
		//	cout << tmp << "所对应的名字:"  << Nm[tmp] << ":" << i << "duiy"<< Sum[i] <<"befsor" << ans[tmp].Total<< endl;

		ans[tmp].Head = Nm[tmp];
		ans[tmp].Total += Sum[i];
		//			cout << tmp << "所对应的名字:"  << Nm[tmp] << ":" << i << "duiy"<< Sum[i] <<"after" << ans[tmp].Total<< endl;

		ans[tmp].Num++;
	}
	for(map<int, Node>::iterator it=ans.begin(); it!=ans.end(); it++) {
		if(it->second.Total > 2*k && it->second.Num>2) {
			V.push_back(it->second);
		}
	}
	cout << V.size() << endl;
	sort(V.begin(), V.end(), cmp);
	for(int i=0; i<V.size(); i++) {
		cout << V[i].Head << " " << V[i].Num << endl;
	}

	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值