hdu 4009 Transfer water

http://acm.hdu.edu.cn/showproblem.php?pid=4009

最小树形图。题意是有n个地方需要供水,每个地方都可以选择是自己挖井,还是从别的地方引水,根据方法不同和每个地方的坐标不同,花费也不同,现在给出每个地方的坐标,花费的计算方法,以及每个地方可以给哪些地方供水(即对方可以从这里引水),求给所有地方供水的最小花费。

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <cstring>
  4 #include <algorithm>
  5 #define maxn 1005
  6 using namespace std;
  7 const int inf=1<<29;
  8 
  9 int in[maxn],id[maxn];
 10 int vis[maxn];
 11 int pre[maxn];
 12 int cnt;
 13 struct node
 14 {
 15     int x,y,z;
 16 }p[maxn*maxn];
 17 
 18 int dis(int i,int j)
 19 {
 20     return abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y)+abs(p[i].z-p[j].z);
 21 }
 22 
 23 struct node1
 24 {
 25     int u,v,w;
 26 }edg[maxn*maxn];
 27 
 28 int MST(int root,int V,int E)
 29 {
 30     int ans=0;
 31     while(1)
 32     {
 33         for(int i=0; i<V; i++) in[i]=inf;
 34         for(int i=0; i<E; i++)
 35         {
 36             int u=edg[i].u;
 37             int v=edg[i].v;
 38             if(edg[i].w<in[v]&&u!=v)
 39             {
 40                 pre[v]=u; in[v]=edg[i].w;
 41             }
 42         }
 43         in[root]=0;
 44         pre[root]=root;
 45         for(int i=0; i<V; i++)
 46         {
 47             ans+=in[i];
 48             if(in[i]==inf) return -1;
 49         }
 50         memset(vis,-1,sizeof(vis));
 51         memset(id,-1,sizeof(id));
 52         cnt=0;
 53         for(int i=0; i<V; i++)
 54         {
 55             int t=i;
 56             while(vis[t]!=i&&id[t]==-1&&t!=root)
 57             {
 58                 vis[t]=i;
 59                 t=pre[t];
 60             }
 61             if(t!=root&&id[t]==-1)
 62             {
 63                 for(int u=pre[t]; u!=t; u=pre[u]) id[u]=cnt;
 64                 id[t]=cnt++;
 65             }
 66         }
 67         if(cnt==0) break;
 68         for(int i=0; i<V; i++)
 69         {
 70             if(id[i]==-1) id[i]=cnt++;
 71         }
 72         for(int i=0; i<E; i++)
 73         {
 74             int u=edg[i].u;
 75             int v=edg[i].v;
 76             edg[i].u=id[u];
 77             edg[i].v=id[v];
 78             if(id[u]!=id[v]) edg[i].w-=in[v];
 79         }
 80         V=cnt;
 81         root=id[root];
 82     }
 83     return ans;
 84 }
 85 
 86 int main()
 87 {
 88     int n,a,b,c;
 89     while(scanf("%d%d%d%d",&n,&a,&b,&c)!=EOF)
 90     {
 91         if(n==0&&a==0&&b==0&&c==0) break;
 92         int t1=0;
 93         for(int i=1; i<=n; i++)
 94         {
 95             scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
 96             edg[t1].u=0; edg[t1].v=i;
 97             edg[t1++].w=a*p[i].z;
 98         }
 99         for(int i=1; i<=n; i++)
100         {
101            int k,v;
102            scanf("%d",&k);
103            for(int j=0; j<k; j++)
104            {
105                scanf("%d",&v);
106                if(v==i) continue;
107                edg[t1].u=i; edg[t1].v=v;
108                edg[t1].w=dis(i,v)*b;
109                if(p[i].z<p[v].z)
110                {
111                    edg[t1].w+=c;
112                }
113                t1++;
114            }
115         }
116         printf("%d\n",MST(0,n+1,t1));
117     }
118     return 0;
119 }
View Code

 

posted @ 2014-05-20 21:17  null1019  阅读(190)  评论(0编辑  收藏  举报