图论---Prim堆优化(稀疏图)
-
题目通常会提示数据范围:
-
若
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;
}