HDU 1875 畅通工程再续——最小生成树

先遍历所有节点求出所有节点间的距离,然后用Kruskal算法求最小生成树。

#include 
#include 
#include 
#include 
#include 

using namespace std;

const int maxn = 110;

int par[maxn], ran[maxn];

void init(int n) {
    for (int i = 0; i <= n; i++) {
        par[i] = i, ran[i] = 0;
    }
}

int seek(int x) {
    if (par[x] == x) return x;
    else return par[x] = seek(par[x]);
}

void unite(int x, int y) {
    x = seek(x), y = seek(y);
    if (x == y) return;
    if (ran[x] == ran[y]) par[x] = y;
    else {
        par[y] = x;
        if (ran[x] == ran[y]) ran[x]++;
    }
}

struct Edge {
    int u, v;
    double cost;
    bool operator < (const Edge &another) const {
        return cost < another.cost;
    }
}edge[maxn*maxn];

struct Node {
    int x, y;
}node[maxn];

double cal(int x1, int y1, int x2, int y2) {
    return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}

int main()
{
    int T, n;
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d %d", &node[i].x, &node[i].y);
        }
        int edge_cnt = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                double temp = cal(node[i].x, node[i].y, node[j].x, node[j].y);
                if (temp < 10 || temp > 1000) continue;
                edge_cnt++;
                edge[edge_cnt].u = i, edge[edge_cnt].v = j, edge[edge_cnt].cost = temp * 100.0;
            }
        }
        sort(edge + 1, edge + 1 + edge_cnt);
        init(n);
        int cnt = 0;
        double ans = 0.0;
        for (int i = 1; i <= edge_cnt; i++) {
            if (cnt == n - 1) break;
            if (seek(edge[i].u) != seek(edge[i].v)) {
                cnt++;
                ans += edge[i].cost;
                unite(edge[i].u, edge[i].v);
            }
        }
        if (cnt == n - 1) printf("%.1lf\n", ans);
        else printf("oh!\n");
    }
    return 0;
}


你可能感兴趣的:(图论)