HDU 4009 Transfer water
Posted GFY
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于HDU 4009 Transfer water的主要内容,如果未能解决你的问题,请参考以下文章
HDU4009 Transfer water —— 最小树形图 + 超级点