HDU 4009 Transfer water

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

题意:给出一个村庄(x,y,z)。每个村庄可以挖井或者修建水渠从其他村庄得到水。挖井有一个代价,修水渠有一个代价。另外A村庄只能向其指定的一些村庄供水。使得所有村庄有水求最小代价。

思路,建立源节点0,向每个点连边视为挖井,如果从其他村庄得到水就相当于从那个点引一条有向边过来。

 1 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 const int inf=1000000000;
 7 int tot,In[1000005],vis[1000005],pre[1000005],id[1000005];
 8 int X,Y,Z,n;
 9 struct Point{
10     int x,y,z;
11 }p[1000005];
12 struct edge{
13     int u,v,w;
14 }e[1300005];
15 void insert(int x,int y,int z){
16     tot++;
17     e[tot].u=x;
18     e[tot].v=y;
19     e[tot].w=z;
20 }
21 int dis(Point p1,Point p2){
22     int ans=std::abs(p1.x-p2.x)+std::abs(p1.y-p2.y)+std::abs(p1.z-p2.z);
23     ans*=Y;
24     if (p1.z<p2.z) ans+=Z;
25     return ans;
26 }
27 int directedMST(int rt){
28     int res=0;
29     while (1){
30         for (int i=0;i<n;i++) In[i]=inf;
31         for (int i=1;i<=tot;i++){
32             int u=e[i].u,v=e[i].v;
33             if (u!=v&&In[v]>e[i].w) In[v]=e[i].w,pre[v]=u;
34         }
35         for (int i=0;i<n;i++){
36             if (i==rt) continue;
37             if (In[i]==inf) return -1;
38         }
39         int cnt=0;
40         for (int i=0;i<n;i++) vis[i]=id[i]=-1;
41         In[rt]=0;
42         for (int i=0;i<n;i++){
43             res+=In[i];
44             int v=i;
45             while (vis[v]!=i&&id[v]==-1&&v!=rt){
46                 vis[v]=i;
47                 v=pre[v];
48             }
49             if (v!=rt&&id[v]!=-1){
50                 for (int j=pre[v];j!=v;j=pre[j]){
51                     id[j]=cnt;
52                 }
53                 id[v]=cnt++;
54             }
55         }
56         if (cnt==0) return res;
57         for (int i=0;i<n;i++) if (id[i]==-1) id[i]=cnt++;
58         int all=0;
59         for (int i=1;i<=tot;i++){
60             int v=e[i].v,u=e[i].u;
61             e[i].u=id[u];
62             e[i].v=id[v];
63             if (e[i].u!=e[i].v)
64              e[i].w-=In[v],e[++all]=e[i];
65         }
66         tot=all;
67         n=cnt;rt=id[rt];
68     }
69     return res;
70 }
71 int main(){
72     while (scanf("%d%d%d%d",&n,&X,&Y,&Z)!=EOF&&n){
73         if (!n&&!X&&!Y&&!Z) return 0;
74         for (int i=1;i<=n;i++) scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
75         for (int i=1;i<=n;i++){
76             int k,x;
77             scanf("%d",&k);
78             while (k--){
79                 scanf("%d",&x);
80                 if (x==i) continue;
81                 insert(i,x,dis(p[i],p[x]));
82             }
83             insert(0,i,p[i].z*X);        
84         }
85         n++;
86         int Ans=directedMST(0);
87         printf("%d\n",Ans);
88     }
89 }

 

posted @ 2016-05-27 19:46  GFY  阅读(222)  评论(0编辑  收藏  举报