最小生成树(prim算法)
https://www.luogu.com.cn/problem/P3366
使用 \(vis\) 标记访问过节点,小顶堆存边以及边指向的点。初始将 \(vis_1\) 标记为 \(true\),将 \(1\) 的边全部加入优先队列。对于堆中元素 \([d,u]\),如果 \(vis_u=false\),这条边就为树边,对 \(u\) 所有的边 \([w,v]\),如果 \(vis[v]=false\),就加入优先队列中。
//author:kzssCCC
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void solve(){
int n,m;
cin >> n >> m;
vector<vector<pair<int,int>>> adj(n+1);
for (int i=0;i<m;i++){
int u,v,w;
cin >> u >> v >> w;
adj[u].emplace_back(w,v);
adj[v].emplace_back(w,u);
}
vector<bool> vis(n+1,false);
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<>> pq;
vis[1] = true;
for (auto& [w,v]:adj[1]){
if (!vis[v]){
pq.emplace(w,v);
}
}
int res = 0;
int cnt = 0;
while (!pq.empty()){
auto [d,u] = pq.top();
pq.pop();
if (vis[u]) continue;
vis[u] = true;
res += d;
cnt++;
for (auto& [w,v]:adj[u]){
if (!vis[v]){
pq.emplace(w,v);
}
}
}
if (cnt!=n-1){
cout << "orz\n";
}
else{
cout << res << '\n';
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t = 1;
// cin >> t;
while (t--) solve();
return 0;
}

浙公网安备 33010602011771号