方法:用深度遍历,同时计算每个连通分量的结点数,及点权最大的结点。
注意点:1,输出的连通分量要求,结点数>2且点权之和大于指定值;2,题中有至多1000个记录,但至多会有2000个不同的名字。
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=2010;
map<string,int> mp;
map<int,string> mp2; //数字到名字的映射
vector<int> child[maxn];
int N,K,weight[maxn]={0},index=0; //index记录所有电话记录包含的人数
map<string,int> gang;
bool vis[maxn]={0};
void DFS(int v,int &num,int &headindex,int &sumw,int &maxw){
vis[v]=true;
num++;
sumw+=weight[v];
if(weight[v]>maxw){
headindex=v;
maxw=weight[v];
}
for(int i=0;i<child[v].size();i++){
if(vis[child[v][i]]==false){
DFS(child[v][i],num,headindex,sumw,maxw);
}
}
}
void DFStrav(){
int numgang=0;
for(int i=0;i<index;i++){
if(vis[i]==false){
int num=0,headindex=-1,sumw=0,maxw=-1;
DFS(i,num,headindex,sumw,maxw);
if(num<=2||sumw<=2*K) continue;
gang[mp2[headindex]]=num;
numgang++;
}
}
printf("%d\n",numgang);
}
int main(){
scanf("%d%d",&N,&K);
string s1,s2;
int time;
for(int i=0;i<N;i++){
cin>>s1>>s2>>time;
if(mp.find(s1)==mp.end()){
mp[s1]=index++;
mp2[index-1]=s1;
}
weight[mp[s1]]+=time;
if(mp.find(s2)==mp.end()){
mp[s2]=index++;
mp2[index-1]=s2;
}
weight[mp[s2]]+=time;
child[mp[s1]].push_back(mp[s2]);
child[mp[s2]].push_back(mp[s1]);
}
DFStrav();
for(map<string,int>::iterator it=gang.begin();it!=gang.end();it++){
cout<<it->first<<" "<<it->second<<endl;
}
return 0;
}