这个题不需要按图的遍历和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;
}