【codevs】2796 最小完全图 | Kruskal

题意

若一个图的每一对不同顶点都恰有一条边相连,则称为完全图。

最小生成树MST在Smart的指引下找到了你,希望你能帮它变成一个最小完全图(边权之和最小的完全图)。

注意:必须保证这个最小生成树MST对于最后求出的最小完全图是唯一的。

数据范围

30%的数据:n<1000;

100%的数据:n≤20000,所有的边权<231

题解

1、Kruskal 求最小生成树

  先将边按照边权从小到大排序。

  然后按顺序检查该边的两个端点如果在两个集合中,那么合并它们,直到所有点都在同一集合中。

#include <cstdio>
#include <algorithm>

const int MAXN = 100050;

int n, dad[MAXN], ans;

struct Edge {
    int form, to, pow;
    bool operator < (Edge a) {
        return pow < a.pow;
    }
} edge[MAXN];

void addE(int x, int y, int z, int ma) {
    edge[ma].form = x;
    edge[ma].to = y;
    edge[ma].pow = z;
}

int getdad(int x) {
    return dad[x] == x ? x : getdad(dad[x]);
}

int main() {
    scanf("%d", &n);
    
    for (int i = 1; i <= n; i++) dad[i] = i;
    
    for (int i = 1; i < n; i++) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        addE(a, b, c, i);
    }
    
    std::sort(edge + 1, edge + n);
    
    for (int i = 1; i <= n; i++) {
        int u = edge[i].form, v = edge[i].to;
        if (getdad(u) != getdad(v)) dad[u] = getdad(dad[v]), ans += edge[i].pow;
    }    
    
    printf("%d\n", ans);
    return 0;
}
Kruskal

 2、对于这一道题,给我们最小生成树,要求求出最小完全图。

  一开始所有点都在不同的集合中, 我们每读入一次边就是将该边的端点所在的两个集合连上一条边,但我们想让这两个集合完全联通,也就是说把两个集合中的元素两两连边,要注意的一点是这些边的权值至少是我们读入的那条边的权值加一,否则将不满足必须保证这个最小生成树MST对于最后求出的最小完全图是唯一的 

AC代码

#include <cstdio>
#include <iostream>
#include <algorithm>
#define ll long long

const int MAXN = 100050;

int n;
ll dad[MAXN], sz[MAXN], ans;

struct Edge {
    int from, to;
    ll pow;
/*    bool operator < (Edge a) {            // 辣鸡 codevs!!!为什么不让我用 operator !!! 
        return pow < a.pow;
    }*/
} e[MAXN];

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

void addE(int x, int y, int z, int ma) {
    e[ma].from = x;
    e[ma].to = y;
    e[ma].pow = z;
}

int getdad(int x) {
    return dad[x] == x ? x : getdad(dad[x]);
}

int main() {
    scanf("%d", &n);                                
    
    ans = 0;
    for (int i = 1; i <= n; i++) dad[i] = i, sz[i] = 1;
    
    for (int i = 1; i < n; i++) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        addE(a, b, c, i);
    //    printf("%d\n", e[i].pow);
    }
    
    std::sort(e + 1, e + n, cmp);
    
    for (int i = 1; i < n; i++) {
        int u = getdad(e[i].from), v = getdad(e[i].to);
        ans += sz[u] * sz[v] * (e[i].pow + 1) - 1;
        dad[u] = v, sz[v] += sz[u];
    }
    
    printf("%lld\n", ans);
    return 0;
}
辣鸡 codevs,害我 CE

 

posted @ 2017-10-20 17:40  E-Valley  阅读(201)  评论(0)    收藏  举报