最小生成树(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;
}
posted @ 2026-06-02 09:58  kzssCCC  阅读(9)  评论(0)    收藏  举报