其实就是找连通块的个数,每个联通块的边总权值求出来,只不过有点小变化
①节点是字符串,因此用map<string,int>存节点,并且开个string数组name
可以通过name[] 找到之前节点的名字
②每个连通块内可能存在环,因此在求每个连通块的边总权值时,向下遍历的条件需要改,遍历时vis[i]==0这个条件略微改一下,并且每发现一个边加上其权值之后就断开此边。
#include<bits/stdc++.h>
#define inf 999999999
using namespace std;
int n,k;
map<string,int> m,mm;
string name[2005];
int mapp[2005][2005],vis[2005],sum,t,people,head,dis[2005],maxx;
void dfs(int x)
{
people++;
vis[x]=1;
if(dis[x]>maxx) //寻找头目
{
head=x;
maxx=dis[x];
}
for(int i=1;i<t;i++)
{
if(mapp[x][i]>0) //这里不设vis判定,目的是保证加完所有的边的权值
{
sum+=mapp[x][i];
mapp[x][i]=mapp[i][x]=0; //加完之后断边,确保每条边只加一次
if(vis[i]==0)
dfs(i);
}
}
}
int main()
{
cin>>n>>k;
string s1,s2;
int w;
t=1;
for(int i=1;i<=n;i++) //存距离
{
cin>>s1>>s2>>w;
int a,b;
if(m[s1]==0)
{
m[s1]=t;
a=t;
name[t]=s1;
t++;
}
else
a=m[s1];
if(m[s2]==0)
{
m[s2]=t;
b=t;
name[t]=s2;
t++;
}
else
b=m[s2];
mapp[a][b]+=w;
mapp[b][a]+=w;
dis[a]+=w; //每个点的权值
dis[b]+=w;
}
int cnt=0;
for(int i=1;i<t;i++) //找连通块
{
if(vis[i]==0)
{
sum=0;
head=0;
people=0;
maxx=0;
dfs(i);
if(people>2 && sum>k) //若此连通块满足条件
mm[name[head]]=people;
}
}
cout<<mm.size()<<endl;
for(map<string,int>::iterator it=mm.begin();it!=mm.end();it++)
cout<<(*it).first<<" "<<(*it).second<<endl;
return 0;
}