最小树形图

关于最小树形图, 看了下资料和研究了一下代码 。

熟悉了最小树形图的结构还有朱刘算法的大概过程。

最小树形图 跟 最小生成树有两点不同之处: 一有向 、二有根 。

简而言之 , 是能够从根到达各个节点 , 所构成的有向图 , 要求边权之和最小 。

对于朱刘算法 ,有4个步骤 。

1.判断是否存在最小树形图 。

2.对图进行标记,判环,无环则可返回。

2.将图中的环缩成点。

3.构成新图。

double zhuliu( int root ) {
    double res = 0 ; int u , v ;
    while(1) {
        for( int i = 0 ; i < n ; ++i ) in[i] = inf ;

        for( int i = 0 ; i < m ; ++i )
            if( e[i].u != e[i].v && e[i].w < in[e[i].v] ) {
                pre[e[i].v] = e[i].u;
                in[e[i].v] = e[i].w;
            }
        for( int i = 0 ; i < n ; ++i )
            if( i != root && in[i] == inf )
                return -1 ;
        int tn = 0 ;
        memset( id , -1 , sizeof id );
        memset( vis , -1 , sizeof vis );
        in[root] = 0 ;
        for( int i = 0 ; i < n ; ++i ) {
            res += in[i];
            v = i ;
            while( vis[v] != i && id[v] == -1 && v != root ) {
                vis[v] = i ;
                v = pre[v] ;
            }
            if( v != root && id[v] == -1 ) {
                for( int u = pre[v] ; u != v ; u = pre[u] )
                    id[u] = tn ;
                id[v] = tn++ ;
            }
        }
        if( tn == 0 ) break ; // no circle
        for( int i = 0 ; i < n ; ++i ) if( id[i] == -1 ) {
            id[i] = tn++ ;
        }
        for( int i = 0 ; i < m ; ){
            v = e[i].v;
            e[i].u = id[e[i].u];
            e[i].v = id[e[i].v];
            if( e[i].u != e[i].v )
                e[i++].w -= in[v];
            else
                swap( e[i] , e[--m] );
        }
        n = tn ;
        root = id[root];
    }
    return res ;
}

时间: 2024-12-08 09:18:46

最小树形图的相关文章

bzoj4349: 最小树形图

最小树形图模板题…… 这种\(O(nm)\)的东西真的能考到么…… #include <bits/stdc++.h> #define N 60 #define INF 1000000000 using namespace std; int n, m, nn; double ai[N], an[N], ci[2][N][N], ans; int bc[N]; int ini[N], vis[N], inc[N], inl[N]; int dfn; int dfs(int t) { vis[t]

Directed_MST 最小树形图

List Directed_MST 最小树形图 List Knowledge 模板 Practice 参考资料 Knowledge 求一个图中遍历到每个点的方案中的最小边权和,显然n-1条边,即一颗树即可. 最小生成树?当然这里不是的,这里的最小树形图算法是针对有向图的. 最小树形图的第一个算法是1965年朱永津和刘振宏提出的复杂度为O(VE)的算法.简称朱刘算法. 1986年, Gabow, Galil, Spencer和Tarjan提出了一个复杂度更好的实现,其时间复杂度为O(E+VlogV

hdu2121+不定根最小树形图

算和定根最小树形图相同. 我们只需:设一个权值sumw=所有边之和+1,类似于网络流,向图中加入一个超级源点,把这个点作为虚根.虚根到其他所有点之间连上一条边,边权值为sumw. 求出的值减去sumw即为最小树形图的权值. 当然,返回-1则无解.此外,当求出的值>=2*sumw,也是无解的. 1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 struct node 5 { 6 int u,v; 7

HDOJ 2121 Ice_cream’s world II 最小树形图无根树

朱刘算法 最小树形图无根树: 建立一个虚拟的根节点,向所有节点连边,权值为其他所有边的权值和+1 在求最小树形图的时候,记录和虚拟的根相连的是哪个节点 在这题中,边是从小往大加的所以直接记录的是相连的是第几号边.... Ice_cream's world II Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3442    Accept

最小树形图【模板】

基于贪心和缩点的思想. 假设根的顶点是V0. (1)除了根结点外,所有的点Vi,找到以Vi为终点的最短的边,加入集合中 (pre[v]存放的是终点v的起点,In[v]存放终点为v的最短的边) (2)检查集合中有没有有向环和收缩点.若没有有向环和收缩点,结束计算:若没有有向环.但含收缩边,则跳至步骤(4):若含有有向环,则跳至步骤(3).Ps:如果出现重边,将忽略权值较高的 (3)含有有向环,则收缩有向环(缩点),把有向环收缩为一个点,其有向环内的边被收缩掉,而环外的边被保 留,构建新图,重复步骤

HDU 2121 Ice_cream’s world II (不定根最小树形图)

题目地址:HDU 2121 这题没有给定根.最容易想到的当然是暴力,枚举所有的根,但是TLE是显然的..为了处理不定根的情况,可以虚拟一个根,然后用这个根去跟所有的点连边,权值为其他所有权值的和+1,目的是防止成为最小树形图的一条边.然后跑出最小树形图后,那么这个虚拟根肯定跟一个实际根相连,这时候根就找到了,然后再在最终的总花费中减去虚拟的那条边的权值就可以了. 代码如下: #include <iostream> #include <string.h> #include <m

HDU2121 Ice_cream’s world II【最小树形图】【不定根】

Ice_cream's world II Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3005    Accepted Submission(s): 704 Problem Description After awarded lands to ACMers, the queen want to choose a city be he

poj Command Network 最小树形图

规定根节点,求一颗生成树使得权值最小,但由于是有向图,所以最小生成树算法失效. 查资料后得知此类问题叫做最小树形图. 解决最小树形图问题的朱刘算法,算法核心基于找 [最小弧集->找环,消环缩点] 的思想,来慢慢构造树形图. 所有的灵魂都在这张图上.0.0 注意缩点后的弧权值的处理 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algo

AIZU AOJ 2309 Vector Compression 最小树形图(朱—刘算法)

题意简述:给定若干个相同维度的向量,寻找一种排序方法,使得所有向量的表示长度总和最低. 所谓表示长度为(Aj-r*Ai)^2,其中i<j  数据范围:向量总数和维度均小于100 思路:(1)首先Ai和Aj确定后,最小表示长度是可以在线性时间计算出来的.使用简单的二次函数分析方法即可. (2)上述可以得出任意两向量之间的距离,即为图中的边,于是问题可以转化为有向图的"最小树形图",i到j的有向边权值即为用Aj表示Ai的最小表示长度. (3)朱-刘算法简述: 首先对除根以外的点选择一

HDU 2121 Ice_cream’s world II 最小树形图

这个题就是需要求整个有向带权图的最小树形图,没有指定根,那就需要加一个虚根 这个虚根到每个点的权值是总权值+1,然后就可以求了,如果求出来的权值大于等于二倍的总权值,就无解 有解的情况,还需要输出最根,多解的情况,肯定是某个环上所有的点为根都可以(比如所有的点构成一个环), 这样加边的时候虚边的时候按照点的标号从小到大编,这样第一个以虚根为前驱的点也是最小的点就可以标记(标记一下) #include <iostream> #include <algorithm> #include