HDU 1879 继续畅通工程 (最小生成树--Kruscal)

来源:互联网 发布:搜狐邮箱smtp端口 编辑:程序博客网 时间:2024/06/11 19:25

Discription

省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。现得到城镇道路统计表,表中列出了任意两城镇间修建道路的费用,以及该道路是否已经修通的状态。现请你编写程序,计算出全省畅通需要的最低成本。

Input

测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1< N < 100 );随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:1表示已建,0表示未建。

当N为0时输入结束。

Output

每个测试用例的输出占一行,输出全省畅通需要的最低成本。

Sample Input

3
1 2 1 0
1 3 2 0
2 3 4 0
3
1 2 1 0
1 3 2 0
2 3 4 1
3
1 2 1 0
1 3 2 1
2 3 4 1
0

Sample Output

3
1
0

Solution

对已经建好的公路进行unite,建立edge数组,套用模板即可

code

#include <iostream>#include <cstdio>#include <algorithm>#include <vector>#include <cstring>using namespace std;struct Edge{    int u, v, w;};const int INF = 0x3f3f3f3f;const int maxn = 110;Edge e[maxn * (maxn - 1) / 2];int pre[maxn];int N;void init(){    for (int i = 1; i <= N; i++)        pre[i] = i;}int find(int x){    if (x == pre[x])        return x;    return pre[x] = find(pre[x]);}void unite(int i, int j){    if (find(i) != find(j))        pre[find(j)] = find(i);}bool cmp(Edge a, Edge b){    if (a.w != b.w)        return a.w < b.w;    if (a.u != b.u)        return a.u < b.u;    return a.v < b.v;}int kruskal(int cnt){    sort(e + 1, e + 1 + cnt, cmp);    int ans = 0;    for (int i = 1; i <= cnt; i++)    {        if (find(e[i].u) != find(e[i].v))        {            unite(e[i].u, e[i].v);            ans += e[i].w;        }    }    return ans;}int main(){    // freopen("in.txt", "r", stdin);    while (~scanf("%d", &N) && N)    {        init();        int cnt = 1;        for (int i = 1; i <= N * (N - 1) / 2; i++)        {            int a, b, c, d;            scanf("%d%d%d%d", &a, &b, &c, &d);            if (d == 0)                e[cnt].u = a, e[cnt].v = b, e[cnt++].w = c;            else                unite(a, b);        }        int ans = kruskal(cnt - 1);        printf("%d\n", ans);    }    return 0;}
阅读全文
0 0
原创粉丝点击