• 洛谷4716 【模板】最小树形图


    类似于最小生成树一样的东西

    就是以给定的rt为根的最小外向生成树【内向直接建反边也行

    然后算法是朱刘算法 大体过程就是先贪心选每个点的最小入边 然后暴力找环

    没有环的话就是算法结束 返回即可 不然就是把这个环缩成一个点然后他的入边都要-=mn[v]就是拥有相同终点的边需要减掉变成增加量一样

    如果要输出方案的话就需要还原 还原的话记录一下哪些边用过然后拆环即可

    这个玩意时间复杂度貌似是O(nm)

    但是我请教了一下巨佬们 大概这个是最劣复杂度 一般是不会达到的

    可以理解为O(能过)就行了

    代码如下。

    //Love and Freedom.
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define inf 20021225
    #define ll long long
    #define N 110
    #define M 10010
    using namespace std;
    
    struct edge{int u,v,c;}e[M];
    int pre[N],mn[N],id[N],vis[N];
    int n,m;
    int zlal(int rt)
    {
        int res = 0;
        while(1)
        {
            for(int i=1;i<=n;i++)    mn[i] = inf;
            for(int i=1;i<=m;i++)
                if(e[i].u != e[i].v && mn[e[i].v]>e[i].c)
                {
                    mn[e[i].v] = e[i].c; pre[e[i].v] = e[i].u;
                }
            for(int i=1;i<=n;i++)    if(i!=rt && mn[i]==inf)    return -1;
            int tn = 0,u,v;
            memset(id,0,sizeof(id)); memset(vis,0,sizeof(vis));
            mn[rt] = 0;
            for(int i=1;i<=n;i++)
            {
                res += mn[i]; v=i;
                while(v!=rt && !id[v] && vis[v]!=i)
                    vis[v] = i, v = pre[v];
                if(v!=rt && !id[v])
                {
                    ++tn;
                    for(u=pre[v];u!=v;u=pre[u])
                        id[u] = tn;
                    id[v] = tn;
                }
            }
            if(!tn)    break;
            for(int i=1;i<=n;i++)    if(!id[i])
                id[i] = ++tn;
            for(int i=1;i<=m;i++)
            {
                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].c -= mn[v];
            }
            n = tn; rt = id[rt];
        }
        return res;
    }
    int main()
    {
        int r;    scanf("%d%d%d",&n,&m,&r);
        for(int i=1;i<=m;i++)    scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].c);
        printf("%d
    ",zlal(r));
        return 0;
    }
    /**
    3 2 1
    1 3 0
    3 2 1
    */
    View Code
  • 相关阅读:
    window.open打开新窗体并用post方式传参
    开发环境搭建问题及解决
    JavaScript高级程序设计(二)
    JavaScript高级程序设计(一)
    JS 小技巧整理
    Windows7版本了解
    安装mysql8.0.17时候报错1251-Client does not support authentication protocol requested by server; consider upgrading MySQL client
    idea中gradle的springboot的项目热部署
    idea多行注释缩进
    idea的类头注释和方法注释的编辑
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/10366713.html
Copyright © 2020-2023  润新知