1348:【例49】城市公交网建设问题

【题目描述】

有一张城市地图,图中的顶点为城市,无向边代表两个城市间的连通关系,边上的权为在这两个城市之间修建高速公路的造价,研究后发现,这个地图有一个特点,即任一对城市都是连通的。现在的问题是,要修建若干高速公路把所有城市联系起来,问如何设计可使得工程的总造价最少?

【输入】

n(城市数,1<≤n≤100)

e(边数)

以下e行,每行3个数i,j,wiji,j,wij,表示在城市i,j之间修建高速公路的造价。

【输出】

n-1行,每行为两个城市的序号,表明这两个城市间建一条高速公路。

【输入样例】

5 8
1 2 2
2 5 9
5 4 7
4 1 10
1 3 12
4 3 6
5 3 3
2 3 8

【输出样例】

1  2
2  3
3  4
3  5

#include <bits/stdc++.h>
using namespace std;

struct Node {
    int x, y, w;

    Node(int x, int y, int w)
    {
        this->x = x;
        this->y = y;
        this->w = w;
    }

    bool operator<(const Node &b) const
    {
        return (w > b.w);
    }
};

void show(vector<vector<int>> &a)
{
    for (int i = 1; i < a.size(); i++) {
        for (int j = 1; j < a[i].size(); j++) {
            cout << setw(2) << a[i][j] << " ";
        }
        cout << endl;
    }
}

vector<pair<int, int>> prim(vector<vector<int>> &a)
{
    vector<pair<int, int>> ans; // 边集
    unordered_set<int> vs; // // 点集
    vs.insert(1); // 从点1开始
    for (int t = 2; t < a.size(); t++) { // 次数
        priority_queue<Node> es; // 边集
        for (auto &v : vs) { // 遍历起点
            for (int i = 1; i < a.size(); i++) {
                if (vs.find(i) != vs.end()) {
                    continue; // 点j在vs中
                }
                es.push(Node(v, i, a[v][i]));
            }
        }
        Node nt = es.top(); // 取最短的边
        ans.push_back(make_pair(nt.x, nt.y));
        vs.insert(nt.y);
    }
    return ans;
}


int main()
{
    // freopen("in.txt", "r", stdin);
    int n, e; // 城市数n,边数e
    scanf("%d%d", &n, &e);
    vector<vector<int>> a(n + 1, vector<int>(n + 1, INT_MAX));
    int x, y, w;
    for (int i = 0; i < e; i++) {
        scanf("%d%d%d", &x, &y, &w);
        a[x][y] = a[y][x] = w;
    }
    // show(a);
    vector<pair<int, int>> ae = prim(a);
    sort(ae.begin(), ae.end());
    for (auto &e : ae) {
        printf("%d %d\n", e.first, e.second);
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/gaojs/p/15584356.html