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 }