标签: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; }
标签:end 并查集 维护 dijkstra name ring a算法 put memset
原文地址:https://www.cnblogs.com/1starfish/p/9451493.html