HDOJ 4009-Transfer water最小树形图解题报告

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

这道题是说一个村庄里的人家住在不同的位置,而且有不同的高度,每户人家可以自己修建水井,也可以选择从别的人家修建引水渠,并且回因为位置的高低产生不同的费用,首先,每户人家都可以选择自己修建水井,所以不存在无解的情况,然后,建立一个虚拟根,从根出发到第i个节点有权值为这户人家自己修建水井的费用,如果i能从j引水,从j到i建立一条权值为修建引水渠费用的边,最后要找的就是这个有向图的最小树形图。关于最小树形图百度百科有详细的描述和算法介绍,可以参照代码进行比对。

View Code
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #define N 1005
  5 #define inf 0x7fffffff
  6 using namespace std;
  7 struct point
  8 {
  9     int x,y,z;
 10 };
 11 int Abs(int a)
 12 {
 13     return a<0?-a:a;
 14 }
 15 point p[N];
 16 int dis(point p1,point p2)
 17 {
 18     return Abs(p1.x-p2.x)+Abs(p1.y-p2.y)+Abs(p1.z-p2.z);
 19 }
 20 int cnt;
 21 struct node
 22 {
 23     int u,v,w;
 24 };
 25 node e[N*N];
 26 int n,id[N],vis[N],pre[N],in[N];
 27 void init()
 28 {
 29     cnt=0;
 30 }
 31 void add(int u,int v,int w)
 32 {
 33     e[cnt].u=u,e[cnt].v=v,e[cnt++].w=w;
 34 }
 35 int directedMST(int root)
 36 {
 37     int res=0,cntnode,nv=n;
 38     int i,j,k,u,v;
 39     while(1)
 40     {
 41         for(i=0;i<nv;i++)
 42         {
 43             in[i]=inf;
 44         }
 45         for(i=0;i<cnt;i++)
 46         {
 47             u=e[i].u;
 48             v=e[i].v;
 49             if(in[v]>e[i].w&&u!=v)
 50             {
 51                 pre[v]=u;
 52                 in[v]=e[i].w;
 53             }
 54         }
 55         for(i=0;i<nv;i++)
 56         {
 57             if(i==root)
 58             continue;
 59             if(in[i]==inf)
 60             return -1;
 61         }
 62         in[root]=0;
 63         memset(id,-1,sizeof(id));
 64         memset(vis,-1,sizeof(vis));
 65         cntnode=0;
 66         for(i=0;i<nv;i++)
 67         {
 68             res+=in[i];
 69             v=i;
 70             while(vis[v]!=i&&id[v]==-1&&v!=root)//找自环
 71             {
 72                 vis[v]=i;
 73                 v=pre[v];
 74             }
 75             if(v!=root&&id[v]==-1)//缩点
 76             {
 77                 for(u=pre[v];u!=v;u=pre[u])
 78                 id[u]=cntnode;
 79                 id[v]=cntnode++;
 80             }
 81         }
 82         if(cntnode==0)
 83         break;
 84         for(i=0;i<nv;i++)
 85         if(id[i]==-1)
 86         id[i]=cntnode++;
 87         for(i=0;i<cnt;i++)
 88         {
 89             v=e[i].v;
 90             e[i].u=id[e[i].u];
 91             e[i].v=id[e[i].v];
 92             if(e[i].u!=e[i].v)
 93             e[i].w-=in[v];
 94         }
 95         nv=cntnode;
 96         root=id[root];
 97     }
 98     return res;
 99 }
100 int main()
101 {
102     int X,Y,Z,u,v,i,j,k,cost;
103     while(scanf("%d%d%d%d",&n,&X,&Y,&Z)&&(n||X||Y||Z))
104     {
105         init();
106         n++;
107         for(i=1;i<n;i++)
108         {
109             scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
110             add(0,i,p[i].z*X);
111         }
112         for(i=1;i<n;i++)
113         {
114             scanf("%d",&k);
115             while(k--)
116             {
117                 scanf("%d",&u);
118                 if(u==i)
119                 continue;
120                 cost=dis(p[u],p[i])*Y;
121                 if(p[u].z>p[i].z)
122                 cost+=Z;
123                 add(i,u,cost);
124             }
125         }
126         printf("%d\n",directedMST(0));
127     }
128     return 0;
129 }
posted @ 2012-09-06 14:57  zhenhai  阅读(229)  评论(0编辑  收藏  举报