数据有问题,方法对了交上没问题。
一个最小生成树的题。安慰时间Ci是点的权值,Li是边的权值。题目还要选定一个点作为往返点,任意选择节点遍历,发现只有起始点是被经过次数最多的,那么要满足题目要求时间最小,即选择权值最小的节点作为起点,要往返,经过每个农场都要花费c【i】的时间和奶牛交谈,所以此条边为边权×2加上点权作为Kruskal的权重,最后加上一次起点权值,就是最小生成树的权值。
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
struct node
{
int a,b,l;
}edg[200005];
int c[10005];
int n,m,f[50005],ans=0,t=0;
bool cmp(node a,node b)
{
return a.l<b.l;
}
int find(int x)//查找x的爸爸
{
if(x==f[x]) return x;//如果x的爸爸是自己,他就是总爸爸
else return f[x]=find(f[x]);
//x认最后的总爸爸当爸爸,相当于路径压缩
}
void merg(int a,int b)//合并函数
{
int fa=find(a),fb=find(b);
if(fa!=fb) f[fa]=fb;
//a(fa)的总爸爸认b(fb)的总爸爸当爸爸
}
int main()
{
int mi=inf;
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>c[i],mi=min(mi,c[i]);
//cout<<mi<<endl;
for(int i=1;i<=n;i++)
f[i]=i;//每个人的爸爸都是自己
for(int i=1;i<=m;i++)
{
cin>>edg[i].a>>edg[i].b>>edg[i].l;
edg[i].l=2*edg[i].l+c[edg[i].a]+c[edg[i].b];
}
sort(edg+1,edg+m+1,cmp);//按照边集排序
for(int i=1;i<=m;i++)
{
if(find(edg[i].a)!=find(edg[i].b))
merg(edg[i].a,edg[i].b), ans+=edg[i].l,t++;
//如果总爸爸不是一个人,合并到一起
if(t==n-1)
break;
}
cout<<ans+mi<<endl;
return 0;
}