• HDU 6141 I am your Father!(最小树形图)


    【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=6141

    【题目大意】

      给出一个有向图,求1点为根的最小树形图使得第n个点的直接父亲编号最小

    【题解】

      如果没有第n个点直接父亲编号最小的要求,
      那么只要跑一遍朱刘算法即可,考虑到直接父亲最小的条件,
      我们连向第n个点的所有边进行加权操作,
      使得其在总边权相同的情况选取答案具有优先性

    【代码】

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long LL; 
    const int N=1010,M=10010;
    const LL INF=0x3f3f3f3f3f3f3f3f;
    int ROOT;
    struct DMST{
        int n,size,pre[N],id[N],vis[N];
        LL in[N];
        struct EDGE{
            int u,v; LL cost;
            EDGE(){}
            EDGE(int a,int b,int c):u(a),v(b),cost(c){}
        }E[M];
        void init(int _n){n=_n,size=0;}
        void add(int u,int v,int w){E[size++]=EDGE(u,v,w);}
        LL dmst(int root){
            int u,v,cnt;
            LL ret=0;
            while(1){
                for(int i=0;i<n;i++)in[i]=INF;
                for(int i=0;i<size;i++){
                    u=E[i].u,v=E[i].v;
                    if(E[i].cost<in[v]&&u!=v){
                        pre[v]=u,in[v]=E[i].cost;
                        if(u==root)ROOT=i;
                    }
                }
                for(int i=0;i<n;i++)if(i!=root&&in[i]==INF)return -1;
                cnt=in[root]=0;
                for(int i=0;i<n;i++)id[i]=vis[i]=-1;
                for(int i=0;i<n;i++){
                    ret+=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(u=pre[v];u!=v;u=pre[u])id[u]=cnt;
                        id[v]=cnt++;
                    }
                }
                if(!cnt)break;
                for(int i=0;i<n;i++)if(id[i]==-1)id[i]=cnt++;
                for(int i=0;v=E[i].v,i<size;i++){
                    E[i].u=id[E[i].u],E[i].v=id[E[i].v];
                    if(E[i].u!=E[i].v)E[i].cost-=in[v];
                }n=cnt,root=id[root];
            }return ret;
        }
    }U;
    int T,n,m;
    int main(){
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&m);
            U.init(n);
            while(m--){
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                z*=1000; if(y==n)z+=n-x;
                U.add(x-1,y-1,-z);
            }LL ans=-U.dmst(0);
            int fa=n-ans%1000;
            ans/=1000;
            printf("%lld %d
    ",ans,fa);
        }return 0;
    }
  • 相关阅读:
    写给自己:青年员工交流会会议记录
    写给自己:金融小白的考证之路
    写给自己:入职初体验
    反欺诈体系
    政策&定价&风控审批策略
    你还在寻找Navicat的破解版本?你应该了解开源免费的DBeaver
    规则引擎在IoT的重要性?
    轻松上手SpringBoot Security + JWT Hello World示例
    Kafka 系列-1
    JDK14-ZGC调研初探
  • 原文地址:https://www.cnblogs.com/forever97/p/hdu6141.html
Copyright © 2020-2023  润新知