歌名 - 歌手
0:00

    修路

    题解

    这里写图片描述

    分析

    因为每个城市的贡献度为\(a[i]*(i这个城市它所直接相连的城市数)\),实际上就是指它的出度或入度的个数,每一个出度或入度,它都会有贡献值\(a[i]\)
    那么,也就是给连接它的边减去\(a[i]\)
    所以,对于一条边\((x,y)\),就把它的花费减去\(a[x]+a[y]\).
    然后跑一边最小生成树就可以了。

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    const long long maxlongint=2147483647;
    const long long mo=1000000007;
    const long long N=100005;
    using namespace std;
    long long a[N],n,m,ans,fa[N];
    struct ddx
    {
    	long long x,y,cost;
    }b[N];
    bool cmp(ddx x,ddx y)
    {
    	return x.cost<y.cost;
    }
    long long get(long long x)
    {
    	if(x==fa[x]) return x;
    	fa[x]=get(fa[x]);
    	return fa[x];
    }
    int main()                                 
    {                                    
    	scanf("%lld%lld",&n,&m);         
    	for(int i=1;i<=n;i++) fa[i]=i;
    	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%lld%lld%lld",&b[i].x,&b[i].y,&b[i].cost);
    		b[i].cost-=a[b[i].x]+a[b[i].y];
    	}
    	sort(b+1,b+m+1,cmp);
    	for(int k=0,i=1;i<=m && k<n-1;i++)
    	{
    		int x=get(b[i].x),y=get(b[i].y);
    		if(x!=y)
    		{
    			fa[x]=y;
    			ans+=b[i].cost;
    		}
    	}
    	printf("%lld",ans);
    }                                          
                                               
    
    posted @ 2018-05-09 12:35  无尽的蓝黄  阅读(149)  评论(0编辑  收藏  举报