您的位置:首页 > Web前端

HDU 4009 Transfer water(最小树形图)

2016-03-13 20:47 411 查看
Description

给出n户人家的位置(xi,yi,zi),一户人家可以别人家引进水源,也可以自己凿井,第一种方案的花费是两家哈密顿距离*Y,如果该户人家的海拔比引进水源的人家高,那么还有额外花费Z,第二种方案的花费是该户人家的海拔*X,问使得所有人家都有水的最小花费是多少,如果没有满足条件的方案则输出poor xiaoA

Input

多组用例,每组用例第一行为四个整数n,X,Y,Z,之后n行每行三个整数表示该户人家的坐标,之后n行每行首先输入一个整数num表示该户人家可以供水的人家数量,之后num个整数表示该户人家可以供水的人家编号,以0 0 0 0结束输入

Output

对于每组用例,如果存在可行方案则输出最小花费,否则输出”poor xiaoA”

Sample Input

2 10 20 30

1 3 2

2 4 1

1 2

2 1 2

0 0 0 0

Sample Output

30

Solution

在有供水关系的人家间建边,构造超级源点0,从0向每户人家i建zi*X的边表示该户人家自己凿井的花费,之后就是求这张图的最小树形图了

Code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 1111
struct Edge
{
int u,v,c;
}edge[maxn*maxn];
int pre[maxn],id[maxn],vis[maxn],in[maxn];
int zhuliu(int root,int n,int m)
{
int ans=0,u,v;
while(1)
{
for(int i=0;i<n;i++)in[i]=INF;
for(int i=0;i<m;i++)
if(edge[i].u!=edge[i].v&&edge[i].c<in[edge[i].v])
{
pre[edge[i].v]=edge[i].u;
in[edge[i].v]=edge[i].c;
}
for(int i=0;i<n;i++)
if(i!=root&&in[i]==INF)
return -1;
int res=0;
memset(vis,-1,sizeof(vis));
memset(id,-1,sizeof(id));
in[root]=0;
for(int i=0;i<n;i++)
{
ans+=in[i];
v=i;
while(vis[v]!=i&&id[v]==-1&&v!=root)
{
vis[v]=i;
v=pre[v];
}
if(id[v]==-1&&v!=root)
{
for(u=pre[v];u!=v;u=pre[u])
id[u]=res;
id[v]=res++;
}
}
if(res==0)break;
for(int i=0;i<n;i++)
if(id[i]==-1)
id[i]=res++;
for(int i=0;i<m;)
{
v=edge[i].v;
edge[i].u=id[edge[i].u];
edge[i].v=id[edge[i].v];
if(edge[i].u!=edge[i].v)
edge[i++].c-=in[v];
else swap(edge[i],edge[--m]);
}
n=res;
root=id[root];
}
return ans;
}
struct node
{
int x,y,z;
}p[maxn];
int get_dis(node a,node b)
{
return abs(a.x-b.x)+abs(a.y-b.y)+abs(a.z-b.z);
}
int main()
{
int n,m,X,Y,Z;
while(scanf("%d%d%d%d",&n,&X,&Y,&Z),n)
{
for(int i=1;i<=n;i++)scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
m=0;
for(int i=1;i<=n;i++)
{
int num,j;
scanf("%d",&num);
while(num--)
{
scanf("%d",&j);
edge[m].u=i,edge[m].v=j,edge[m].c=get_dis(p[i],p[j])*Y;
if(p[j].z>p[i].z)edge[m].c+=Z;
m++;
}
}
for(int i=1;i<=n;i++)
edge[m].u=0,edge[m].v=i,edge[m++].c=p[i].z*X;
int ans=zhuliu(0,n+1,m);
if(ans!=-1)printf("%d\n",ans);
else printf("poor XiaoA\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: