• HDU 4009 Transfer water 最小树形图


    分析:建一个远点,往每个点连建井的价值(单向边),其它输水线按照题意建单向边

    然后以源点为根的权值最小的有向树就是答案,套最小树形图模板

    #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=1e3+5;
    const int INF=0x7f7f7f7f;
    struct Edge{
        int u,v;
        LL w;
    }edge[N*N];
    struct Node{
      LL x,y,z;
    }p[N];
    LL in[N];
    int id[N],vis[N],pre[N],n,m;
    LL zhuliu(int rt,int n,int m){
         int ret=0;
         while(1){
         for(int i=1;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]){
                pre[edge[i].v]=edge[i].u;
                in[edge[i].v]=edge[i].w;
            }
         }
         for(int i=1;i<=n;++i)
         if(i!=rt&&in[i]==INF)return -1;
         int cnt=0;
         memset(id,-1,sizeof(id));
         memset(vis,-1,sizeof(vis));
         in[rt]=0;
         for(int i=1;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==0)break;
         for(int i=1;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;   
    }
    LL dis(int i,int j){
      return abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y)+abs(p[i].z-p[j].z);
    }
    int main()
    {
        LL X,Y,Z;
        while(~scanf("%d%I64d%I64d%I64d",&n,&X,&Y,&Z)){
            if(!n)break;
            for(int i=1;i<=n;++i)
               scanf("%I64d%I64d%I64d",&p[i].x,&p[i].y,&p[i].z);
            int cnt=0;
            for(int i=1;i<=n;++i){
                int k;
                scanf("%d",&k);
                for(int j=1;j<=k;++j){
                    int u=i,v;
                    scanf("%d",&v);
                    if(u==v)continue;
                    ++cnt;
                    edge[cnt].u=u,edge[cnt].v=v;
                    edge[cnt].w=dis(u,v)*Y;
                    if(p[u].z<p[v].z)edge[cnt].w+=Z;
                }
            }
            for(int i=1;i<=n;++i){
                ++cnt;
                edge[cnt].u=n+1;
                edge[cnt].v=i;
                edge[cnt].w=X*p[i].z;
            }
            LL ans=zhuliu(n+1,n+1,cnt);
            printf("%I64d
    ",ans); 
        }
        return 0;
    }
    View Code
  • 相关阅读:
    活着就是幸福
    ibatis配置log4j输出sql语句等日志信息
    每天记录点点滴滴
    SSH整合 创建SessionFactory
    活着
    最经典的智力题
    struts整合spring整合hibernate
    让MyEclipse里的Tomcat自动reloadable
    明天就会有阳光...
    数据表字段为空时的判断
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5479869.html
Copyright © 2020-2023  润新知