Codeforces Contest 1095 problem F Make It Connected——最小生成树

You are given an undirected graph consisting of n vertices. A number is written on each vertex; the number on vertex i is ai. Initially there are no edges in the graph.

You may add some edges to this graph, but you have to pay for them. The cost of adding an edge between vertices x and y is ax+ay coins. There are also m special offers, each of them is denoted by three numbers x, y and w, and means that you can add an edge connecting vertices x and y and pay w coins for it. You don’t have to use special offers: if there is a pair of vertices x and y that has a special offer associated with it, you still may connect these two vertices paying ax+ay coins for it.

What is the minimum number of coins you have to spend to make the graph connected? Recall that a graph is connected if it’s possible to get from any vertex to any other vertex using only the edges belonging to this graph.

Input
The first line contains two integers n and m (1≤n≤2⋅105, 0≤m≤2⋅105) — the number of vertices in the graph and the number of special offers, respectively.

The second line contains n integers a1,a2,…,an (1≤ai≤1012) — the numbers written on the vertices.

Then m lines follow, each containing three integers x, y and w (1≤x,y≤n, 1≤w≤1012, x≠y) denoting a special offer: you may add an edge connecting vertex x and vertex y, and this edge will cost w coins.

Output
Print one integer — the minimum number of coins you have to pay to make the graph connected.

Examples
inputCopy
3 2
1 3 3
2 3 5
2 1 1
outputCopy
5
inputCopy
4 0
1 3 3 7
outputCopy
16
inputCopy
5 4
1 2 3 4 5
1 2 8
1 3 10
1 4 7
1 5 15
outputCopy
18
Note
In the first example it is possible to connect 1 to 2 using special offer 2, and then 1 to 3 without using any offers.

In next two examples the optimal answer may be achieved without using special offers.

题意:

给你n个点的权值,链接两个点的代价是ax+ay,之后给你m个特殊的边,链接两个点的值可以为w,你可以选择用或者不用,问你使所有点链接起来最小代价是多少。

题解:

刚开始想错了。。其实只要把所有的点与权值最小的点连线,然后与特殊边放到一起做最小生成树即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2e5+5;
struct node
{
    int x,y;
    ll w;
    node(){}
    node(int x,int y,ll w):x(x),y(y),w(w){}
    bool operator< (const node& a)const
    {
        return w<a.w;
    }
}e[N*4];
ll a[N];
int fa[N];
int finds(int x)
{
    return x==fa[x]?fa[x]:fa[x]=finds(fa[x]);
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    ll minn=1e17,pos=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        if(a[i]<minn)
            minn=a[i],pos=i;
        fa[i]=i;
    }
    for(int i=1;i<=m;i++)
        scanf("%d%d%lld",&e[i].x,&e[i].y,&e[i].w);
    for(int i=1;i<=n;i++)
    {
        if(i==pos)
            continue;
        e[++m]=node(i,pos,a[i]+a[pos]);
    }
    sort(e+1,e+m+1);
    ll ans=0;
    for(int i=1;i<=m;i++)
    {
        int x=finds(e[i].x);
        int y=finds(e[i].y);
        if(x!=y)
        {
            ans+=e[i].w;
            fa[y]=x;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值