tyvj1659中中救援队

题目:http://www.joyoi.cn/problem/tyvj-1659

发现每条边要走两次,每个点要走它连接的边数次。

所以把边的权值赋成 本身的值+两个端点的点权,求最小生成树即可。

!边权其实是 本身的值*2+两个端点的点权;

别忘了起点要多加一次,所以找一个点权最小的加上即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,a[10005],fa[10005],x,y,tmp;
long long ans=1005;
struct Edge{
    int x,y,w;
    Edge(int x=0,int y=0,int w=0):x(x),y(y),w(w) {}
}edge[100005];
bool cmp(Edge x,Edge y){return x.w<y.w;}
int find(int a)
{
    if(fa[a]==a)return a;
    return fa[a]=find(fa[a]);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),fa[i]=i,ans=min(ans,(long long)a[i]);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&tmp);
        edge[i]=Edge(x,y,a[x]+a[y]+tmp+tmp);
    }
    sort(edge+1,edge+m+1,cmp);
    for(int i=1;i<=m;i++)
    {
        int u=edge[i].x,v=edge[i].y;
        if(find(u)!=find(v))
        {
//            printf("u=%d v=%d plu=%d
",u,v,edge[i].w);
            fa[fa[u]]=fa[v];ans+=edge[i].w;
        }
    }
    printf("%lld",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/Narh/p/8627815.html