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