最小生成树MST(Prim/Kruskal模版)

来源:互联网 发布:韩国美颜软件 编辑:程序博客网 时间:2024/05/18 12:37

生成树:如果连通图G的一个子图是一棵包含G的所有顶点的树,则该子图称为G的生成树。生成树不唯一,不同起点遍历所得生成树不同。
最小生成树:边权最小的生成树。

最小边原则:图中权值最小的边(如果唯一的话)一定在最小生成树上。

唯一性:一棵生成树上,如果各边的权都不相同,则最小生成树是唯一的。反之不然。

生成树一定是无向图。

Prim

基础是两个属性:
环属性:一棵生成树上,增加一条边e,再删除e所在环上的最大边,会得到另一棵“更好”的生成树(如果e不是最大边)
剪切属性:在图中,剪切将顶点划分成两个不相交集合。交叉边为这些顶点在两个不同集合的边。对于任何一个剪切,各条最小的交叉边都属于某个MST,且每个MST中都包含一条最小交叉边。

简述:MST_Prim(G, r)
(1)将G剪切成两个集合A、B,A中只有一个点r
(2)取最小权的交叉边(x,y),x∈A, y∈B
(3)将y加入A并更新
(4)如果已经加了n-1条边,结束。否则,转 (3)

示例
这里写图片描述

模版

int flag[maxm]={};//是否在A中。int dis[maxm];//集合A与i点的交叉边权值,如果flag[i]==1,那么dis[i]无意义。int sum=0;//MST边权总和。void prim(){    flag[1]=1;//从任意一点出发均可,此处用第一个点。第一个点已被选入集合A。    for(int i=1;i<=n;i++) dis[i]=a[1][i];//初始化。    dis[1]=0; //已在A中,无交叉边。    for(int i=1;i<n;i++)    {        int minn=1000000;        int k=0;        for(int j=1;j<=n;j++)            if(!flag[j]&&dis[j]<minn) minn=dis[j],k=j;//在现有的交叉边中找到最小的。        flag[k]=1;//将其加入A。        sum+=dis[k];        if(k==0) break;//同dijkstra,非联通图的情况。        for(int j=1;j<=n;j++)            if(!flag[j]&&dis[j]>a[k][j]) dis[j]=a[k][j];//利用新加入的点更新集合A与B的交叉边。    }    return; }

基于点的迭代,稳定O(n^2)。
堆优化后:O((|E|+|V|)*log|V|) ,适合稀疏图。



Kruskal

简述:MST_Kruskal(G)
(1)将G所有条边按权从小到大排序;图mst开始为空
(2)从小到大次序取边(x,y)
(3)若加入边(x,y),mst就有环,则放弃此边,转(2)
(4)将边(x,y)加入mst,如果已经加了n-1条边,结束。否则,转 (2)

判环即利用并查集,改日另写。

int n,m,summ=0;struct edge{    int q,w,v;}e[maxm];//边表。int fa[maxn]={};//根节点。sort(e+1,e+m+1,mycmp);//升序排序。for(int i=1;i<=n;++i) fa[i]=i;//根节点初始化。inline int find(int x){    if(fa[x]==x) return x;    fa[x]=find(fa[x]);    return fa[x];}//找爸爸。/*或者另一种装13的找爸爸写法:inline int find(int x){    return(fa[x]==x?x:fa[x]=find(fa[x]));}*/void kru(){    int flag=0;//边数计数器。    for(int i=1;i<=m;i++)    {        int x=find(e[i].q);        int y=find(e[i].w);        if(x!=y)//如果它们不是同一个爸爸生的,即加入它们不会形成一个环。        {            fa[x]=y;//合并。            flag++;//计数。            summ+=e[i].v;            if(flag==n-1) return;//如果边已达到n-1条,结束。        }    }    return;}

基于边的迭代,适合稀疏图,O(|E|*log|E| +|N|*A(|V|))。O(|E|*log|E| )用于排序。