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\n",ans); 
    }
    return 0;
}
View Code

 

posted @ 2016-05-10 23:34  shuguangzw  阅读(137)  评论(0编辑  收藏  举报