1034 Head of a Gang (30 分)

题目

题目链接

题解

并查集。


注意坑点:帮派的人数必须大于2。


代码

#include<bits/stdc++.h>
using namespace std;
#define PSI pair<string,int>
const int N = 1e5+10;

int n, k, cnt;
int fa[N];

int gongw[N]; // 每个人对于帮派的贡献,同一个通话只用记录一个人的,因为如果两个人都修改gongw,最后累加的时候会变成两倍 
int w[N]; // 每个人的通话时间,两个人都要加,为了找帮派首领 
int num[N]; // num[i] 表示以i为代表的帮派的人数,注意,代表与首领的不同,代表是find(x),而首领只是本题中的概念 
int head[N]; // head[i] 表示以i为代表的帮派的首领 
int teamw[N]; // teamw[i] 表示以i为代表的帮派的总权重,累加该帮派的gongw即可 

map<string, int> nti; // name to int:将名字转为对应的索引 
map<int, string> itn; // int to name:将索引转为对应的名字 

set <int> s;

vector <PSI> v;

int find (int x) {
	return fa[x] == x ? x : fa[x] = find (fa[x]);
}

void join (int x, int y) {
	int rx = find (x), ry = find (y);
	if (rx != ry) fa[rx] = ry;
}

int main()
{
	cin >> n >> k;
	
	for (int i = 0;i < N;i ++) fa[i] = i;
	
	for (int i = 0;i < n;i ++) {
		string aa, bb;
		int c, a, b;
		cin >> aa >> bb >> c;
		
		if (!nti[aa]) nti[aa] = ++ cnt, itn[cnt] = aa;
		a = nti[aa];
		
		if (!nti[bb]) nti[bb] = ++ cnt, itn[cnt] = bb;
		b = nti[bb];
		
		join (a, b);
		gongw[a] += c;
		w[a] += c;
		w[b] += c;
	}
	
	for (int i = 1;i <= cnt;i ++) {
		int rt = find (i);
		num[rt] ++;
		teamw[rt] += gongw[i];
		head[rt] = w[head[rt]] < w[i] ? i : head[rt]; // 看看是否要换首领 
		if (teamw[rt] > k) s.insert (rt);
	}
	
	for (int item : s) 
		if (num[item] > 2) // !!!帮派人数必须大于2,题目要求的 
			v.push_back ({itn[head[item]], num[item]});

	sort (v.begin(), v.end());
	
	cout << v.size() << endl;
	for (int i = 0;i < v.size();i ++) 
		cout << v[i].first << ' ' << v[i].second << endl;
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不牌不改

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值