Directed_MST 最小树形图


List

Knowledge

求一个图中遍历到每个点的方案中的最小边权和,显然n-1条边,即一颗树即可。 最小生成树?当然这里不是的,这里的最小树形图算法是针对有向图的。 最小树形图的第一个算法是1965年朱永津和刘振宏提出的复杂度为O(VE)的算法。简称朱刘算法。

1986年, Gabow, Galil, Spencer和Tarjan提出了一个复杂度更好的实现,其时间复杂度为O(E+VlogV)。%啊,又是Tarjan大爷。好像并没有翻到详细的记载,一般用不到。应该有点复杂吧。

下面介绍一下ZLEdmonds:

 
简述:记pre[i]为连到i点所有前驱中边权最小的一个 可以理解如果没有环,那么这个方案即为所求 如果有环肯定就有bug,因为点显然不连通 找环,先默认环上的边都加入答案(后面重构边权会导致最后方案把环上一条边去掉) 缩点将其与其它点连边边权改为w-=w[i→pre[i]],这样最后答案如果连了这条边,环上的点就不要再来一次。 这样缩环后重新找pre,直到不存在环 这样重新构图后,虽然开始有环,但重构的边权会使最后删掉环上的某条边 保证了最后肯定是一个树形图,而且还是最小的

模板

struct Directed_MST{
    static const int N=110,M=N*N;
    static const int/double INF=1e9;
    int m,n,root;
    int/double w[M],s[N],ans;
    int u[M],v[M],pre[N],id[N],f[N];
    void Combine(){
        for(int i=1;i<=m;i++){
            int gg=v[i];u[i]=id[u[i]];v[i]=id[v[i]];
            if(u[i]!=v[i])w[i]-=s[gg];
        }
    }
    void ZLEdmonds(){
        ans=0;
        while(true){
            for(int i=1;i<=n;i++)s[i]=INF;
            for(int i=1;i<=m;i++)
                if(w[i]<s[v[i]]&&u[i]!=v[i])s[v[i]]=w[i],pre[v[i]]=u[i];
            int cnt=1;
            memset(id,-1,sizeof(id));
            memset(f,0,sizeof(f));
            s[root]=0;
            for(int i=1;i<=n;i++){
                ans+=s[i];int x=i;
                while(f[x]!=i&&x!=root)f[x]=i,x=pre[x];
                if(x!=root&&id[x]==-1){
                    for(int o=pre[x];o!=x;o=pre[o])id[o]=cnt;
                    id[x]=cnt++;
                }
            }
            if(cnt==1)break;
            for(int i=1;i<=n;i++)if(id[i]==-1)id[i]=cnt++;
            Combine();n=cnt-1;root=id[root];
        }
        cout<<ans;
    }
}ZL;

Practice

Bzoj1179 Apio2009 Atm(2016-09-20 19:54)

参考资料

Wiki Minimum spanning tree 
Wiki Edmonds’ algorithm

时间: 2024-10-13 08:50:58

Directed_MST 最小树形图的相关文章

最小树形图(有向图)

GGS-DDU http://acm.hdu.edu.cn/showproblem.php?pid=4966 建图待补,先做模板了. 1 #include<cstdio> 2 #include<cstring> 3 #define mt(a,b) memset(a,b,sizeof(a)) 4 const int inf=0x3f3f3f3f; 5 class Directed_MST { ///最小树形图(有向图) 6 typedef int typec;///边权的类型 7 s

poj 3164 最小树形图模板 (优先c++ ,g++ 有时会wa==)

#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include <iostream> #define eps 1e-8 using namespace std; /* 最小树形图图模版-朱刘算法 模版说明:点标号必须0-(N-1) 必须去除到自身的点(到自身的边的边权赋无限大) */ #define M 109 #define type double

HDU4966 GGS-DDU(最小树形图)

之前几天想着补些算法的知识,学了一下最小树形图的朱刘算法,不是特别理解,备了份模板以备不时之需,想不到多校冷不丁的出了个最小树形图,没看出来只能表示对算法不太理解吧,用模板写了一下,然后就过了.- -0 之前听到是最小树形图的时候觉得恍然大悟,非常裸,但是后来想想也不是特别裸,其实关键就是要想清楚要加回流的边,贴一份代码吧- -0 #pragma warning(disable:4996) #include<cstdio> #include<set> #include<cst

POJ--3164--Command Network【朱刘算法】最小树形图

链接:http://poj.org/problem?id=3164 题意:告诉n个点坐标,m条边表示两个点之间有路.从1点開始建立一个有向图最小生成树. 朱刘算法模板题 ========================== 切割线之下摘自user_id=Sasuke_SCUT" style="color:rgb(202,0,0); text-decoration:none; font-family:Arial; font-size:14px; line-height:26px"

无根最小树形图模板

1 #include<iostream> 2 using namespace std; 3 #include<cstdio> 4 #include<cstring> 5 #define MAXN 1005 6 #define INF 0x7f7f7f7f 7 typedef __int64 type; 8 struct node//边的权和顶点 9 { 10 int u, v; 11 type w; 12 }edge[MAXN * MAXN]; 13 int pre[M

UVA - 11183 Teen Girl Squad(最小树形图)

题目大意:给出一张有向图,0为根,求出最小树形图 解题思路:模版题 #include <cstdio> #include <cstring> #define N 1010 #define M 40010 struct Edge{ int u, v, c; }E[M]; int n, m; void init (){ scanf("%d%d", &n, &m); for (int i = 0; i < m; i++) scanf("

HDUOJ--2121--Ice_cream’s world II【朱刘算法】不定根最小树形图

链接:http://acm.hdu.edu.cn/showproblem.php?pid=2121 题意:n个顶点,m条边,求从某一点起建立有向图最小生成树并且花费最小,输出最小花费和根节点下标. 思路:这道题根是不确定的,我们可以先假设一个根,从这个根出发到任何一点的距离(sum)都比原图总权值还大,这样保证了虚拟的边不会是最小入边,也为之后判断是否生成了最小树形图提供方便,从这个点开始建立最小树形图,最后生成出一个结果,很显然虚拟的根只有一条出边,并且出边连接的点就是真实的根. 最后得到的最

【POJ3164】Command Network 最小树形图模板题 重修版

链接: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44935891"); } 我以前的版本 算法构造过程以及傻叉代码+弱版注释见以前博客 http://blog.csdn.net/vmurder/article/details/38819711 最小树形图: 名词解释: 其实就是有向图

UVA 11183 - Teen Girl Squad(最小树形图)

UVA 11183 - Teen Girl Squad 题目链接 题意:本质就是给一个有向图,有一些能连接的边,连接有一个代价,问从0能遍历到所有点的,并且代价最小的最小代价 思路:最小树形图的裸题,用朱刘算法求解,验证一下模板 代码: #include <cstdio> #include <cstring> const int MAXNODE = 1005; const int MAXEDGE = 40005; typedef int Type; const Type INF =