基本算法:\(Kruskal\)算法和\(Prim\)算法
最小生成树(Kruskal(克鲁斯卡尔)和Prim(普里姆))算法动画演示,up主:WAY_zhong
以下代码引用自:题解 P3366 【【模板】最小生成树,作者:yhtwd
//Prim+邻接链表 #include<cstdio> #include<queue> #include<cstring> #include<algorithm> #define R register int using namespace std; int k,n,m,cnt,sum,ai,bi,ci,head[5005],dis[5005],vis[5005]; struct Edge { int v,w,next; }e[400005]; void add(int u,int v,int w) { e[++k].v=v; e[k].w=w; e[k].next=head[u]; head[u]=k; } typedef pair <int,int> pii; priority_queue <pii,vector<pii>,greater<pii> > q; void prim() { dis[1]=0; q.push(make_pair(0,1)); while(!q.empty()&&cnt<n) { int d=q.top().first,u=q.top().second; q.pop(); if(vis[u]) continue; cnt++; sum+=d; vis[u]=1; for(R i=head[u];i!=-1;i=e[i].next) if(e[i].w<dis[e[i].v]) dis[e[i].v]=e[i].w,q.push(make_pair(dis[e[i].v],e[i].v)); } } int main() { memset(dis,127,sizeof(dis)); memset(head,-1,sizeof(head)); scanf("%d%d",&n,&m); for(R i=1;i<=m;i++) { scanf("%d%d%d",&ai,&bi,&ci); add(ai,bi,ci); add(bi,ai,ci); } prim(); if (cnt==n)printf("%d",sum); else printf("orz"); }
然后放个洛谷最高赞,感觉是不是有点奇技淫巧啊。最小生成树浅谈,作者:呢没理他
另外还看到有一个貌似蛮全的总结,生成树专题,作者:October
(这名字好漂亮)
链式前向星详解,作者:ACdreamers
(很熟悉了 不过还是放一下)
priority_queue,作者:Deribs4
Dijkstra:加入b到已拓展节点集合里面后
shortest_path[c] = min( shortest_path[b]+distance[b,c] , shortest_path[c] )
就是看看加入b后会不会源点a通过b而到达c的路径更短,是就更新。
Prim:加入b到已拓展节点集合里面后
min_edge[c] = min( distance[b,c] , min_edge[c] )
就是看看加入b后会不会b到c的枝条长度更短,是就更新。
引用自:Dijkstra 与 Prim 算法的区别,作者:rancho628
这俩个算法都是找出俩个集合,初始状态下,一个集合S只含有源点,另一个(V-S)含有图的其他顶点。然后是从V-S中挑出顶点到S中....但是这俩个算法还是有很大的区别的。
1,prim算法是用来求最小生成树的,而Dijkstra算法是用来求任意俩点间的最短路径问题.
2,边的权值修改方式不同。prim中,对V-S中的任意顶点,如果新进入到S中的顶点K,使得K到该顶点的距离最小,则修改该顶点的权值。而Dijkstra算法中,对v-s中的顶点,如果新加入S的顶点K,使得(源点到K的距离+<Vi,Vk>)小于加入K点前源点到改点的最短距离,则修改该顶点权值。
3,时间复杂度不同。prim算法中,必须求出n个顶点,n-1条边。而Dijkstra算法中最多求n个顶点。
4,出发点不同。prim算法是从任意顶点出发,到所有顶点都进入集合S为止。而Dijkstra算法是从源点开始到汇点结束。
引用自:关于prim算法与dijskra算法得区别,作者:暖阳下的好日子
技术学了蛮多的 但是还是感觉系统性上差了点意思
服了 我数据结构的书不会明年才能到吧