• 最小树形图-朱刘算法


    朱刘算法

    最小树形图

    即:有向图中的最小生成树(外向树)

    大致思路

    1.对每个点求出边权最小的入边,并记录
    2.看1,中组成的图有无环,且能否组成树
    3.若存在环,则将环缩成一个点,重新赋边权,回到1.

    代码

    (洛谷模板)

    #include<bits/stdc++.h>
    using namespace std;
    #define re register
    #define ll long long
    #define get getchar()
    #define in inline
    in int read()
    {
        int t=0; char ch=get;
        while(ch<'0' || ch>'9') ch=get;
        while(ch<='9' && ch>='0') t=t*10+ch-'0', ch=get;
        return t;
    }
    const int _=1e4+23;
    const int inf=0x3f3f3f3f;
    int  rt, n, m;
    struct E{
        int u, v, w;
    }ed[_];
    int id[_], mn[_], pre[_], vis[_];
    ll ans=0;
    in void zhuliu(int n)
    {
        while(1)
        {
            int cnt=0;
            for(re int i=1;i<=n;++i) mn[i]=inf;
            for(re int i=1;i<=m;++i) //找到最小入边
                if(ed[i].w<mn[ed[i].v] && ed[i].u!=ed[i].v)
                    mn[ed[i].v]=ed[i].w, pre[ed[i].v]=ed[i].u;
            for(re int i=1;i<=n;++i) if(i!=rt && mn[i]==inf) {ans=-1;return ;} //判断是否能组成外向树
            for(re int i=1;i<=n;++i) vis[i]=id[i]=0;
            for(re int i=1;i<=n;++i)
            {
                if(i==rt) continue;
                ans+=mn[i];
                int v=i;
                while(vis[v]!=i && !id[v] && v!=rt) vis[v]=i, v=pre[v]; //找环
                if(!id[v] && v!=rt) //把环缩点
                {
                    id[v]=++cnt;
                    for(re int u=pre[v];u!=v;u=pre[u]) id[u]=cnt;
                }
            }
            if(cnt==0) break;
            for(re int i=1;i<=n;++i) if(!id[i]) id[i]=++cnt;
            for(re int i=1;i<=m;++i) //重新赋边权与标号
            {
                int u=ed[i].u, v=ed[i].v;
                ed[i].u=id[u], ed[i].v=id[v];
                if(ed[i].u!=ed[i].v) ed[i].w-=mn[v]; 
            }
            rt=id[rt], n=cnt;
        }
        return ;
    }
    int main()
    {
        n=read(), m=read(), rt=read();
        for(re int i=1;i<=m;++i) ed[i].u=read(), ed[i].v=read(), ed[i].w=read();
        zhuliu(n);
        printf("%lld
    ", ans);
        return 0;
    }
    
    嗯,就这样了...
  • 相关阅读:
    SQL Server 2005 之事务日志体系 (一)
    SQL Server 2005 事务日志之逻辑结构(二)
    SQL Server 2005 清除备份 还原历史记录
    SQL Server 验证器
    SQL Server 2005 事务日志之物理体系(三)
    程序设计语言原理重要概念
    Java作业四 图形用户界面程序设计和多线程
    Java作业二 面向对象程序设计
    Java作业三 语言基础与面向对象
    Java课程学习总结
  • 原文地址:https://www.cnblogs.com/yzhx/p/15253281.html
Copyright © 2020-2023  润新知