图论——最小生成树Kruskal算法模板
2018-03-30 20:13
549 查看
Kruskal算法
1、算法思想:所有边从小到大依次排序(sort、qsort);依次考查每条边(u,v),有两种情况: 情况1:u和v在同一个连通分量中,那么加入(u,v)后会形成环,因此不能选。 情况2:如果不在一个连通分量,那么加入(u,v)一定是最优解,证明反证法:不加(u,v)存在最小生成树的话,那么加上(u,v)一定有且只有一个环,环中至少有一条边(u’,v’)的权值大于(u,v)的权值。那么删除该边后,得到的新树T’=T+(u,v)-(u’,v’)<= T。所以(u,v)是最优解。(很绕可以略过证明) ?问题1—— 判断任意两个点是否在同一个连通分量,还需要合并两个连通分量。 办法1:暴力 (dfs,bfs),算法效率低 办法2:并查集(Union-Find Set)递归思想:把 X 的父节点保存在P[X]中(如果x没有父节点,则P[X])弊端:假如这棵树是长长的一条链,每次查找就会很慢。可以用压缩路径来优化。2、例题:hdu_1863畅通工程以hdu_1863畅通工程为例,Kruskal算法适合稀疏图
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define N 105 int n,m;//n条边,m个结点 struct road{ int xi,yi,vi; }rd ; int par ;//双亲结点 int cmp(road x,road y){ return x.vi<y.vi ; } int Unfind(int x){//并查集_查找,压缩路径 if(!par[x])return x; int i=x; while(par[i]) i=par[i]; int j=x,temp; while(par[j]){ temp=par[j]; par[j]=i; j=temp; } return i; } int main(){ while(~scanf("%d%d",&m,&n)&&n!=0){ memset(rd,0,sizeof(rd));//初始化结构体 memset(par,0,sizeof(par));//初始化双亲结点 for(int i=0;i<n;i++){ scanf("%d%d%d",&rd[i].xi,&rd[i].yi,&rd[i].vi); } sort(rd,rd+n,cmp); int res=m,ans=0; for(int i=0;i<n&&res>1;i++){ int nx=Unfind(rd[i].xi); int ny=Unfind(rd[i].yi); if(nx!=ny){//不是同一个连通分量合并 res--; printf("**%d\n",rd[i].vi); ans+=rd[i].vi; par[nx]=ny; } } if(res==1)//判断是否能生成树,边数等于结点数减 1 printf("%d\n",ans); else printf("?\n"); } }
相关文章推荐
- 「图论」最小生成树-kruskal算法
- 最小生成树(kruskal算法,模板)oj2144
- 最小生成树 kruskal算法(模板)
- 紫书第十一章-----图论模型与算法(最小生成树prim算法和kruskal算法)
- 最小生成树(prim算法与kruskal算法)(模板)
- 最小生成树之Kruskal算法(图论) By ACReaper
- 模板整理: 图论---最小生成树
- 图论中最小生成树构造算法之Prim算法和Kruskal算法
- (模板)最小生成树,Kruskal算法
- (复习)图论--最小生成树--Kruskal算法
- 【最小生成树】(模板-kruskal算法)hdu 1863 畅通工程
- 模板整理——图论·最小生成树·Kruskal
- POJ 1861 Network (Kruskal算法+输出的最小生成树里最长的边==最后加入生成树的边权 *【模板】)
- 最小生成树Kruskal算法【模板】 与 并查集 例题:简单 poj 2485 Highways
- 最小生成树(Kruskal算法)模板
- Hihocoder #1098 : 最小生成树二·Kruskal算法 ( *【模板】 )
- 【2018寒假集训Day 8】【最小生成树】Prim和Kruskal算法模板
- 图论——最小生成树Prim算法模板
- 图论-最小生成树-prime算法&Kruskal算法 c++
- 最小生成树(MST)模板---Kruskal算法