1. 程式人生 > >prim算法(最小生成樹)

prim算法(最小生成樹)

operator const top scan node names name prim算法 最短路

其實prim算法和dijkstra算法差不多,不過迪傑斯特拉是算從 s->t 的最短路徑,而prim是算連接全圖的最短路徑

兩者都是從一個起點開始進行廣搜

但克魯斯卡爾算最最小生成樹是把所有邊都排序好然後慢慢添加邊,用並查集維護,因為用到了邊的排序,所以當題目邊比較多是用prim比較好,點比較多是用克魯斯卡爾算法好點

///prim算法 (邊多的用prim)
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
using
namespace std; const int maxn=1e6+5; int n, m; int first[maxn],sign,vis[maxn]; struct Edge { int to; int w; int next; } edge[maxn*2]; void init() { memset(first,-1,sizeof(first)); sign=0; } void add_edge(int u,int v, int w) { edge[sign].to = v; edge[sign].w = w; edge[sign].next
=first[u]; first[u]=sign++; } struct Node { int to, w; Node(int tt,int ww) { to=tt; w=ww; } friend bool operator < (const Node &a, const Node &b) { return a.w > b.w; } }; void prim() { memset(vis,0,sizeof(vis)); priority_queue
<Node>que; que.push(Node(1,0));///從點1 開始連接最小生成樹 int ans=0,cnt=0; while(!que.empty()) { Node now=que.top(); que.pop(); if(!vis[now.to]) { vis[now.to]=1; ans+=now.w;///算生成樹的權值 cnt++;///計數連接了幾條邊 for(int i=first[now.to]; ~i; i=edge[i].next) { int to=edge[i].to; int w=edge[i].w; if(!vis[to]) { que.push(Node(to,w)); } } } } if(cnt==n) { printf("%d\n", ans); } else { puts("?"); } } int main() { while(~scanf("%d%d",&m,&n)&&m) { init(); for(int i=1; i<=m; i++) { int u,v,w; scanf("%d %d %d",&u,&v,&w); add_edge(u,v,w); add_edge(v,u,w); } prim(); } return 0; }

prim算法(最小生成樹)