F. Make It Connected

题目链接:http://codeforces.com/contest/1095/problem/F

 


题意:给你n个点,每个点有个权值,如果在两点之间添一条边,代价为两点权值之和。现在给出m个边可以选择,代价给出,你可以自己建边不选择。问你把这个图连通最小的花费为多少。

 

解题心得:

  很简单的一个题,刚开始想复杂了弄了好久。直接选一个权值最小的点出来,和每一个点之间连一条边,和m条边放在一起,kruskal跑一下就行了。

 


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+100;

int father[maxn], n, m, pos;
ll Min;

ll node[maxn];
struct Edge {
    int s, t;
    ll va;

    Edge(int S, int T, ll Va):
            s(S), t(T), va(Va){};
};

bool cmp(Edge a, Edge b) {
    return a.va < b.va;
}

vector <int> ve[maxn];
vector <Edge> edge;

void init() {
    Min = 1e18;
    scanf("%d%d",&n, &m);
    for(int i=1;i<=n;i++) {
        ve[i].push_back(i);
        scanf("%lld", &node[i]);
        if(node[i] < Min) {
            Min = node[i], pos = i;
        }
        father[i] = i;
    }
    for(int i=0;i<m;i++) {
        int a,b;
        ll va;
        scanf("%d%d%lld", &a, &b, &va);
        edge.push_back(Edge(a, b, va));
    }
    for(int i=1;i<=n;i++) {
        if(i == pos) continue;
        edge.push_back(Edge(pos, i, node[i] + Min));
    }
    sort(edge.begin(), edge.end(), cmp);
}

int find(int x){
    if(father[x] == x)
        return x;
    return father[x] = find(father[x]);
}

void merge(int x,int y) {
    int fx = find(x);
    int fy = find(y);
    father[fy] = fx;
}


int main() {
    //freopen("1.in", "r", stdin);
    //freopen("1.out", "w", stdout);
    init();
    ll ans = 0;
    for(int i=0;i<edge.size();i++) {
        int fx = find(edge[i].s);
        int fy = find(edge[i].t);
        if(fx != fy) {
            ans += edge[i].va;
            merge(fx, fy);
        }
    }
    printf("%lld", ans);
    return 0;
}

 

posted @ 2018-12-30 19:54  GoldenFingers  阅读(296)  评论(0编辑  收藏  举报