朱刘算法

来源:互联网 发布:caffe训练googlenet 编辑:程序博客网 时间:2024/05/03 04:24

算法目的:求最小树形图(可以理解为有向图的最小有根生成树)

大概思路:用类似贪心的思想,不断缩点来求出答案。下面的算法可以求出当根确定的时候的最小树形图。如果是不定根的情况我们可以虚拟一个根,让虚拟根到每个节点的距离为图上所有边的权值之和加一。这样找到最小树形图一定包含且只包含一条新边,减掉这条边的权值就可以了。

算法步骤:1.求出所有点的最小入边
     2.若此时这些边没有形成环,那么显然这些边就形成了最小树形图
     3.将所有的环缩成一个点,对于环上所有的点X,把所有的(X,i,w)变成(new,i,w),所有的(i,X,w)变成(i,X,w-mn[X])
     重复3,直到满足2条件

算法解析:3操作实际相当于先贪心的选择了所有的边,然后再决定删去哪一个。当再次选择一条指向这个环的边时,需要删除这个环上指向这个点的边,所以直接改变这些边的权值,把他们提前减去这个值就好了

int i,j,x,y,tn=-1;            memset(mn,0x3f,sizeof(mn));            memset(vis,0,sizeof(vis));            memset(A,-1,sizeof(A));            EE.clear();            for(i=0;i<E.size();i++)            {                if(E[i].w<mn[E[i].y])                mn[E[i].y]=E[i].w,bef[E[i].y]=E[i].x;            }            for(i=0;i<n;i++)            if(mn[i]==0x3f3f3f3f) return -1;            int ti=0;            for(i=0;i<n;i++)            {                ret+=mn[i];                x=i;ti++;                while(x!=n&&!vis[x]) vis[x]=ti,x=bef[x];                if(x==n||vis[x]!=ti) continue;                tn++;                A[x]=tn;                for(y=bef[x];y!=x;y=bef[y])                A[y]=tn;            }            if(tn==-1) return ret;            for(i=0;i<=n;i++)            if(A[i]==-1) tn++,A[i]=tn;            for(i=0;i<E.size();i++)            if(A[E[i].x]!=A[E[i].y])            EE.push_back((ppp){A[E[i].x],A[E[i].y],E[i].w-mn[E[i].y]});            E=EE;            n=tn;        }
0 0
原创粉丝点击