1034 Head of a Gang (30分)

这个题不需要按图的遍历和DFS之类的写,完全可以只用并查集做题。

并查集需要注意:


① 需要在输入完所有元素以后再计算单个结点的数据
② 需要进行比较来确定并查集father

附本人并查集AC代码:

#include<vector>
#include<string>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
struct Node {
	int i, num;
};
vector<Node>ans;
map<string, int>Ma, Mcount;
map<int, int>Mhead, Mtotal;
map<int, string>Mb;
int N, K, index = 1, cal, father[10010];
int val[10010][10010];
bool flag[10010][10010];
vector < vector<int>>V(10010);
bool cmp(Node&A, Node&B) {
	return Mb[A.i] < Mb[B.i];
}
void init() {
	for (int i = 1; i < 10010; i++)father[i] = i;
}
int findfather(int x) {
	int a = x;
	while (father[x] != x) {
		x = father[x];
	}
	while (father[a] != x) {
		int t = father[a];
		father[a] = x;
		a = t;
	}
	return x;
}
void uni(int x, int y) {
	int fx = findfather(x);
	int fy = findfather(y);
	if (fx != fy) {
		if (Mcount[Mb[fx]] > Mcount[Mb[fy]]) {
			father[fy] = fx;
		}
		else father[fx] = fy;
	}
}
int main() {
	string s1, s2;
	cin >> N >> K;
	init();
	for (int i = 0; i < N; i++) {
		cin >> s1 >> s2 >> cal;
		if (Ma[s1] == 0) {
			Ma[s1] = index;
			Mb[index++] = s1;
		}
		if (Ma[s2] == 0) {
			Ma[s2] = index;
			Mb[index++] = s2;
		}
		val[Ma[s1]][Ma[s2]] =cal;
		if (!flag[Ma[s1]][Ma[s2]]) {
			flag[Ma[s1]][Ma[s2]] = true;
			V[Ma[s1]].push_back(Ma[s2]);
		}
		if (!flag[Ma[s2]][Ma[s1]]) {
			flag[Ma[s2]][Ma[s1]] = true;
			V[Ma[s2]].push_back(Ma[s1]);
		}
	}
	for (int i = 1; i < index; i++) {
		for (int j = 0; j < V[i].size(); j++) {
			Mcount[Mb[i]] += val[i][V[i][j]] + val[V[i][j]][i];
		}
	}
	for (int i = 1; i < index; i++) {
		for (int j = 0; j < V[i].size(); j++) {
			uni(i, V[i][j]);
		}
	}
	for (int i = 1; i < index; i++) {
		int t = findfather(i);
		Mhead[t]++;
		Mtotal[t] += Mcount[Mb[i]];
	}
	for (auto it = Mhead.begin(); it != Mhead.end(); it++) {
		if (it->second <= 2||Mtotal[it->first]<=2*K)continue;
		else {
			ans.push_back({ it->first,it->second });
		}
	}
	sort(ans.begin(), ans.end(), cmp);
	printf("%d\n", ans.size());
	for (int i = 0; i < ans.size(); i++) {
		printf("%s %d\n", Mb[ans[i].i].c_str(), ans[i].num);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值