標籤:end 並查集 維護 dijkstra name ring a演算法 put memset
其實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演算法(最小產生樹)