BUAA OJ 344 拮据的模拟城市【最小生成树】

题目描述

时间限制: 600 ms 内存限制: 8000 kb
EA出品的模拟经营类游戏《模拟城市》,想必好多人都玩过的吧~
Jeffrey虽然喜欢玩,但不代表他是一个好玩家。现在Jeffrey的模拟城市已经濒临破产,原因很简单:他太爱修路了!
悬崖勒马,现在他想保留一些道路,拆除其余的道路,要求是在保证城市的每个区域互相连通的基础上,使道路的总维护费用最小。
为简化问题,假设所有道路每单位长度的维护费用为1。数据保证整个模拟城市是一个连通图。

输入

多组测试数据。 每组数据第一行是两个整数,分别表示有n个区域,m条道路。(1≤n≤103,0≤m≤105)
接下来m行,每行三个整数u、v、l,表示区域u和区域v之间有一条长度为l的双向道路。(1≤u,v≤n,1≤l≤100)

输出

对于每组数据,输出最小总维护费用。

输入样例

6 10
1 2 6
1 3 1
1 4 5
2 3 5
2 5 3
3 4 5
3 5 6
3 6 4
4 6 2
5 6 6

输出样例

15

思路

最小生成树

代码

prim+堆优化

#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>

using namespace std;
typedef long long ll;

struct mstNode {
    int head;
    int tail;
    int weight;

    explicit mstNode(int h = -1, int t = -1, int w = -1) : head(h), tail(t), weight(w) {}

    bool operator>(const mstNode &p) const {
        return weight > p.weight;
    }
};

struct node {
    int rank;
    int weight;

    explicit node(int r = -1, int w = -1) : rank(r), weight(w) {}
};

int n, m;
ll sum;
vector<node> matrix[1001];

inline void prim(int v0) {
    int v, count;
    mstNode selected;
    priority_queue<mstNode, vector<mstNode>, greater<mstNode> > minHeap;
    bool vOfmst[n + 1];
    memset(vOfmst, 0, sizeof(vOfmst));
    vOfmst[v0] = true;
    count = 1;
    v = v0;
    sum = 0;
    while (count < n) {
        for (int i = 0, size = (int) matrix[v].size(); i < size; ++i)
            if (!vOfmst[matrix[v][i].rank])
                minHeap.push(mstNode(v, matrix[v][i].rank, matrix[v][i].weight));

        again:
        selected = minHeap.top();
        minHeap.pop();
        if (!vOfmst[selected.tail]) {
            sum += selected.weight;
            ++count;
            vOfmst[selected.tail] = true;
        } else goto again;
        v = selected.tail;
    }
}

int main() {
    int u, v, w;
    while (~scanf("%d%d", &n, &m)) {
        for (int i = 0; i < m; ++i) {
            scanf("%d%d%d", &u, &v, &w);
            matrix[u].emplace_back(v, w);
            matrix[v].emplace_back(u, w);
        }
        prim(1);

        printf("%lld\n", sum);
        for (int i = 1; i <= n; i++)
            matrix[i].clear();
    }
}

Kruskal

#include <cstdio>
#include <algorithm>

#define MAXN 100005
using namespace std;
int num_V, num_E, ans;

struct Node {
    int to, from, cost;
} road[MAXN];
int Par[MAXN];

bool cmp(const Node &a, const Node &b) {
    return (a.cost < b.cost);
}

void init() {
    for (int i = 0; i < num_E; i++) Par[i] = -1;
}

int Find(int x) {
    int root = x;
    while (Par[root] >= 0) root = Par[root];
    return root;
}

void unite(int x, int y) {
    x = Find(x);
    y = Find(y);
    if (Par[x] < Par[y]) {
        Par[x] += Par[y];
        Par[y] = x;
    } else {
        Par[y] += Par[x];
        Par[x] = y;
    }
}

int kruskal() {
    int nEdge = 0, fees = 0;
    for (int i = 0; i < num_E && nEdge != num_V - 1; i++) {
        if (Find(road[i].from) != Find(road[i].to)) {
            unite(road[i].from, road[i].to);
            fees += road[i].cost;
            nEdge++;
        }
    }
    return fees;
}

int main() {
    while (~scanf("%d%d", &num_V, &num_E)) {
        init();
        for (int i = 0; i < num_E; i++) {
            scanf("%d%d%d", &road[i].from, &road[i].to, &road[i].cost);
        }
        sort(road, road + num_E, cmp);
        ans = kruskal();
        printf("%d\n", ans);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值