这题的话其实不是特别难,但是如果没有特别好的方法,很难拿到满分,而且比较麻烦,但是会一点小小的搜索,拿个十几分还是可以的,比较恶心的题目没有告诉你有多少个点,如果map的话,最多就2000个不同的点,因为它只给你1000条边,我第一次看到这题想到的是搜索,搜的一塌糊涂,拿了17分,后来看到王道上的人都是用并查集做的,所以自己也试了下并查集的做法,这题用并查集能较好的解决2个问题:1在并查集选择father时,优化了的并查集选择树儿子较多的为father,这题可以选择通信量较大的为father 2如何计算一个集合的总通信量,只要枚举每条边,找到这条边属于哪个father,把相应的值加上就好。用搜索的话,个人还是没有拿到满分,这里代码就不献丑了,
并查集代码如下:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<string>
#include<map>
#include<algorithm>
#define N 2001
using namespace std;
map<string,int>cl;
struct node
{
string st,ed;
int d;
}e[N];
int fa[N];
int num[N];
int tot[N];
int t[N];
struct ans
{
string aa;
int bb;
}ans[N];
int getfather(int x)
{
if (fa[x] != x)
fa[x]=getfather(fa[x]);
return fa[x];
}
void un(int a, int b)
{
a = getfather(a);
b = getfather(b);
if(a==b)
return;
if(t[a]>t[b])
{
fa[b]=a;
num[a]+=num[b];
}
else
{
fa[a]=b;
num[b]+=num[a];
}
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
int i,j;
int vnum=0;
cl.clear();
for(i=1;i<=n;i++)
{
string a,b;
int t;
cin >> a >> b >> t;
e[i].st = a;
e[i].ed = b;
e[i].d = t;
if(cl.count(e[i].st)==0)
{
++ vnum;
cl.insert(make_pair(e[i].st,vnum));
}
if(cl.count(e[i].ed)==0)
{
++ vnum;
cl.insert(make_pair(e[i].ed,vnum));
}
}
for (i=1;i<=vnum;i++)
{
fa[i] = i;
t[i] = 0;
tot[i] = 0;
num[i] = 1;
}
for(i=1;i<=n;i++)
{
t[cl[e[i].st]]+=e[i].d;
t[cl[e[i].ed]]+=e[i].d;
}
for(i=1;i<=n;i++)
un(cl[e[i].st],cl[e[i].ed]);
for(i=1;i<=vnum;i++)
fa[i]=getfather(i);
for(i=1;i<=n;i++)
{
int father=getfather(cl[e[i].st]);
tot[father]+=e[i].d;
}
int cnt=0;
for (map<string,int>::iterator it = cl.begin();it != cl.end(); it++)
{
int kk=it->second;
if(tot[kk]>m&&num[kk]>=3&&fa[kk]==kk)
{
ans[++cnt].aa=it->first;
ans[cnt].bb=num[kk];
}
}
printf("%d\n",cnt);
for(i=1;i<=cnt;i++)
cout<<ans[i].aa<<" "<<ans[i].bb<<endl;
}
return 0;
}