1. 题目
2. 思路
使用并查集归属集合
3. 注意点
- 可以使用map<string, string> 模拟int类型的并查集,减少了string和int类型转换的问题
因为c++的map,值如果不存在会自动初始化
map<string, string> father; //定义
// 查找root
string findfather(string x){
if(father[x] == ""){
father[x] = x;
}else{
while(father[x] != x){
x = father[x];
}
}
return x;
}
- 对于集合的总权重的计算, 存放map<string, int> sum
- 如果两个name本来就是一个节点,sum[findfather(n1)] + weight;
- 如果两个name不是一个节点, sum[findfather(n1)] + sum[findfather(n2)] + weight
4. 代码
#include<cstdio>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<string>
using namespace std;
map<string, string> father;
map<string, int> weights;
map<string, int> sum;
string findfather(string x){
if(father[x] == ""){
father[x] = x;
}else{
while(father[x] != x){
x = father[x];
}
}
return x;
}
bool cmp(string s1, string s2){
return weights[s1] > weights[s2];
}
void collect(int k){
vector<string> res;
map<string, set<string> > col;
for(auto a:father){
col[findfather(a.first)].insert(a.first);
}
for(auto a:col){
if(a.second.size() > 2 && sum[findfather(a.first)] > k){
vector<string> temp(a.second.begin(), a.second.end());
sort(temp.begin(), temp.end(), cmp);
res.push_back(temp[0]);
}
}
sort(res.begin(), res.end(), [](string s1, string s2){
return s1 < s2;
});
printf("%d\n", res.size());
for(auto a:res){
printf("%s %d\n", a.c_str(), col[findfather(a)].size());
}
}
int main(){
int n, k;
scanf("%d %d", &n, &k);
char n1[10], n2[10];
int w;
for(int i=0;i<n;i++){
scanf("%s %s %d", n1, n2, &w);
weights[n1] += w;
weights[n2] += w;
string f1 = findfather(n1);
string f2 = findfather(n2);
if(f1 != f2){
sum[f1] += sum[f2];
father[f2] = f1;
}
sum[f1] += w;
}
collect(k);
}
原文地址:https://www.cnblogs.com/d-i-p/p/12404155.html
时间: 2024-10-27 13:46:17