-
题目通常会提示数据范围:
-
若
V ≤ 500
,两种方法均可(朴素Prim更稳)。 -
若
V ≤ 1e5
,必须用优先队列Prim +vector
存图。
-
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int N = 510, INF = 0x3f3f3f3f;
typedef pair<int, int> PII; // (distance, node)
int n, m;
vector<PII> adj[N]; // 邻接表
int dist[N]; // 存储各点到生成树的最小距离
bool st[N]; // 标记是否已加入生成树
int prim() {
memset(dist, 0x3f, sizeof dist);
priority_queue<PII, vector<PII>, greater<PII>> heap; // 小根堆
heap.push({0, 1}); // 从节点 1 开始
dist[1] = 0;
int res = 0, cnt = 0; // cnt 记录已加入生成树的节点数
while (!heap.empty()) {
auto [d, u] = heap.top();
heap.pop();
if (st[u]) continue; // 已加入生成树,跳过
st[u] = true;
res += d;
cnt++;
// 遍历 u 的所有邻边
for (auto [v, w] : adj[u]) {
if (!st[v] && w < dist[v]) {
dist[v] = w;
heap.push({dist[v], v});
}
}
}
return cnt == n ? res : INF; // 如果生成树包含所有节点,返回总权重;否则返回 INF
}
int main() {
cin >> n >> m;
while (m--) {
int a, b, c;
cin >> a >> b >> c;
adj[a].push_back({b, c});
adj[b].push_back({a, c}); // 无向图
}
int t = prim();
if (t == INF) puts("impossible");
else cout << t << endl;
return 0;
}