朱刘算法

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

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

算法步骤:1.求出所有点的最小入边
     2.若此时这些边没有形成环,那么显然这些边就形成了最小树形图
     3.将所有的环缩成一个点,对于环上所有的点X,把所有的(X,i,w)变成(new,i,w),所有的(i,X,w)变成(i,new,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;
        }
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值