• HDU 2121 Ice_cream’s world II 最小树形图


    这个题就是需要求整个有向带权图的最小树形图,没有指定根,那就需要加一个虚根

    这个虚根到每个点的权值是总权值+1,然后就可以求了,如果求出来的权值大于等于二倍的总权值,就无解

    有解的情况,还需要输出最根,多解的情况,肯定是某个环上所有的点为根都可以(比如所有的点构成一个环),

    这样加边的时候虚边的时候按照点的标号从小到大编,这样第一个以虚根为前驱的点也是最小的点就可以标记(标记一下)

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <string>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <vector>
    using namespace std;
    typedef long long LL;
    const int N=2e3+5;
    const LL INF=0x7fffffff;
    struct Edge{
        int u,v;
        LL w;
    }edge[N*N];
    LL in[N];
    int id[N],vis[N],pre[N],n,m,pos;
    LL zhuliu(int rt,int n,int m){
         LL ret=0;
         while(1){
         for(int i=0;i<=n;++i)in[i]=INF;
         for(int i=1;i<=m;++i){
            if(edge[i].u!=edge[i].v&&edge[i].w<in[edge[i].v]){
                if(edge[i].u==rt)pos=i;
                pre[edge[i].v]=edge[i].u;
                in[edge[i].v]=edge[i].w;
            }
         }
         for(int i=0;i<=n;++i)
         if(i!=rt&&in[i]==INF)return -1;
         int cnt=-1;
         memset(id,-1,sizeof(id));
         memset(vis,-1,sizeof(vis));
         in[rt]=0;
         for(int i=0;i<=n;++i){
            ret+=in[i];
            int v=i;
            while(vis[v]!=i&&id[v]==-1&&v!=rt){
                vis[v]=i;
                v=pre[v];
            }
            if(v!=rt&&id[v]==-1){
                ++cnt;
                for(int u=pre[v];u!=v;u=pre[u])
                  id[u]=cnt;
                id[v]=cnt;
            }
         }
         if(cnt==-1)break;
         for(int i=0;i<=n;++i)
         if(id[i]==-1)id[i]=++cnt;
         for(int i=1;i<=m;++i){
            int u=edge[i].u,v=edge[i].v;
            edge[i].u=id[u];
            edge[i].v=id[v];
            if(id[u]!=id[v])edge[i].w-=in[v];
         }
         n=cnt;
         rt=id[rt];
         }
         return ret;   
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m)){
            LL sum=0;
            for(int i=1;i<=m;++i){
              scanf("%d%d%I64d",&edge[i].u,&edge[i].v,&edge[i].w);
              ++edge[i].u,++edge[i].v;
              sum+=edge[i].w;
            }
            ++sum;
            for(int i=m+1;i<=m+n;++i){
               edge[i].u=0,edge[i].v=i-m;
               edge[i].w=sum; 
            }
            LL ans=zhuliu(0,n,n+m);
            if(ans-sum>=sum)printf("impossible
    
    ");
            else printf("%I64d %d
    
    ",ans-sum,pos-m-1);  
        }
        return 0;
    }
    View Code
  • 相关阅读:
    HTTPS和HTTP的区别
    .NET反射、委托技术与设计模式
    中文化和国际化问题权威解析之三:Java中文问题分析
    Windows下Critical Section、Event、Mutex、Semaphores区别
    使用Forms Authentication 身份验证 之 Basic Knowledge
    介绍几个java虚拟机性能监测工具
    理解Semaphore和Mutex
    中文化和国际化问题权威解析之四:Java中文化和国际化攻略
    中文化和国际化问题权威解析之一:字符编码发展历程
    Happy new year!
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5479696.html
Copyright © 2020-2023  润新知