HDU 1879 继续畅通工程

地址

已经有些边连通了,用并查集的话就是先把这些边union了(记录conn,不加opt),再把未确定的边排序然后挨个union;用prim的话把这些边权值赋为0。

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;

const int MAXN = 1e2 + 5;
int N;
int pre[MAXN];
int conn;
int opt;

struct Edge
{
    int n1, n2, w;
    bool operator<(const Edge& e) const
    {
        return w < e.w;
    }
};
vector<Edge> v;

int f(int x)
{
    int f0 = x, f1 = x;
    for (; pre[f0] > 0;)
    {
        f0 = pre[f0];
    }
    for (; pre[f1] > 0;)
    {
        int t = f1;
        f1 = pre[f1];
        pre[t] = f0;
    }
    return f0;
}

bool u(int a, int b)
{
    int f1 = f(a);
    int f2 = f(b);
    if (f1 != f2)
    {
        conn++;
        if (pre[f1] <= pre[f2])
        {
            pre[f1] += pre[f2];
            pre[f2] = f1;
        }
        else
        {
            pre[f2] += pre[f1];
            pre[f1] = f2;
        }
        return true;
    }
    return false;
}

int main()
{
    int a, b, c, d;
    for (; ~scanf("%d", &N);)
    {
        if (N == 0) return 0;
        v.clear();
        memset(pre, -1, sizeof pre);
        conn = 0;
        opt = 0;
        for (int i = 0; i < N*(N - 1) / 2; i++)
        {
            scanf("%d%d%d%d", &a, &b, &c, &d);
            if (d) u(a, b);
            else v.push_back({ a,b,c });
        }
        sort(v.begin(), v.end());
        for (int i = 0; i < v.size(); i++)
        {
            if (conn == N - 1) break;
            if (u(v[i].n1, v[i].n2))
                opt += v[i].w;
        }
        printf("%d\n", opt);
    }
    return 0;
}
posted @ 2017-04-08 16:28  CrossingOver  阅读(98)  评论(0编辑  收藏  举报