题目链接:https://vjudge.net/problem/HDU-4009

Transfer water

Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 5612    Accepted Submission(s): 1997

Problem Description
XiaoA lives in a village. Last year flood rained the village. So they decide to move the whole village to the mountain nearby this year. There is no spring in the mountain, so each household could only dig a well or build a water line from other household. If the household decide to dig a well, the money for the well is the height of their house multiplies X dollar per meter. If the household decide to build a water line from other household, and if the height of which supply water is not lower than the one which get water, the money of one water line is the Manhattan distance of the two households multiplies Y dollar per meter. Or if the height of which supply water is lower than the one which get water, a water pump is needed except the water line. Z dollar should be paid for one water pump. In addition,therelation of the households must be considered. Some households may do not allow some other households build a water line from there house. Now given the 3‐dimensional position (a, b, c) of every household the c of which means height, can you calculate the minimal money the whole village need so that every household has water, or tell the leader if it can’t be done.
 
Input
Multiple cases. 
First line of each case contains 4 integers n (1<=n<=1000), the number of the households, X (1<=X<=1000), Y (1<=Y<=1000), Z (1<=Z<=1000). 
Each of the next n lines contains 3 integers a, b, c means the position of the i‐th households, none of them will exceeded 1000. 
Then next n lines describe the relation between the households. The n+i+1‐th line describes the relation of the i‐th household. The line will begin with an integer k, and the next k integers are the household numbers that can build a water line from the i‐th household. 
If n=X=Y=Z=0, the input ends, and no output for that. 
 
Output
One integer in one line for each case, the minimal money the whole village need so that every household has water. If the plan does not exist, print “poor XiaoA” in one line. 
 
Sample Input
2 10 20 30
1 3 2
2 4 1
1 2
2 1 2
0 0 0 0
 
Sample Output
30

Hint

In 3‐dimensional space Manhattan distance of point A (x1, y1, z1) and B(x2, y2, z2) is |x2‐x1|+|y2‐y1|+|z2‐z1|.

 
Source
 
 
 
 
题解:
1.可知这题肯定有解,因为大不了每一户都自己挖口井。
2.题目其实就是要求:最小树形图的森林。因此我们不能确定根节点,因为根节点可以有多个,那怎么办呢?
3.设置一个超级点,作为虚拟的根节点。把这个超级点连向每一个题目中的点。然后再用此超级点去跑zhuliu算法,得到一个最小树形图(智能的超级点,好评)。可知把超级点去掉后,就是我们要求的最小树形图的森林(当然我们不需要这样做,这里只是方便理解)。
 

代码一:

 #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXM = 1e6+;
const int MAXN = 1e3+; struct Edge
{
int u, v, w;
}edge[MAXM]; int x[MAXN], y[MAXN], z[MAXN];
int pre[MAXN], id[MAXN], vis[MAXN], in[MAXN]; int zhuliu(int root, int n, int m)
{
int res = ;
while(true)
{
for(int i = ; i<n; i++)
in[i] = INF;
for(int i = ; i<m; i++)
if(edge[i].u!=edge[i].v && edge[i].w<in[edge[i].v])
{
pre[edge[i].v] = edge[i].u;
in[edge[i].v] = edge[i].w;
} for(int i = ; i<n; i++)
if(i!=root && in[i]==INF)
return -; int tn = ;
memset(id, -, sizeof(id));
memset(vis, -, sizeof(vis));
in[root] = ;
for(int i = ; i<n; i++)
{
res += in[i];
int v = i;
while(vis[v]!=i && id[v]==- && v!=root)
{
vis[v] = i;
v = pre[v];
}
if(v!=root && id[v]==-)
{
for(int u = pre[v]; u!=v; u = pre[u])
id[u] = tn;
id[v] = tn++;
}
}
if(tn==) break;
for(int i = ; i<n; i++)
if(id[i]==-)
id[i] = tn++; for(int i = ; i<m; )
{
int 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++].w -= in[v];
else
swap(edge[i], edge[--m]);
}
n = tn;
root = id[root];
}
return res;
} int main()
{
int n, m, X, Y, Z;
while(scanf("%d%d%d%d", &n, &X, &Y, &Z)!=EOF)
{
if(!n && !X && !Y && !Z) break; for(int i = ; i<n; i++)
scanf("%d%d%d", &x[i], &y[i], &z[i]); m = ;
for(int i = ; i<n; i++)
{
int num, v;
scanf("%d", &num);
while(num--)
{
scanf("%d", &v); v--;
edge[m].u = i;
edge[m].v = v;
edge[m].w = Y*(abs(x[i]-x[v])+abs(y[i]-y[v])+abs(z[i]-z[v]));
if(z[i]<z[v]) edge[m].w += Z;
m++;
}
//0~n-1为题目中的点, n为人工设置的超级点
//将超级点连到每一个结点,并且设置相应的权值
edge[m].u = n;
edge[m].v = i;
edge[m++].w = z[i]*X;
} int ans = zhuliu(n, n+, m);
printf("%d\n", ans);
}
}

代码二:

 #include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef long long LL;
const double EPS = 1e-;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXM = 1e6+;
const int MAXN = 1e3+; struct Edge
{
int u, v, w;
}edge[MAXM]; int x[MAXN], y[MAXN], z[MAXN];
int pre[MAXN], id[MAXN], vis[MAXN], in[MAXN]; int zhuliu(int root, int n, int m)
{
int res = ;
while(true)
{
for(int i = ; i<n; i++)
in[i] = INF;
for(int i = ; i<m; i++)
if(edge[i].u!=edge[i].v && edge[i].w<in[edge[i].v])
{
pre[edge[i].v] = edge[i].u;
in[edge[i].v] = edge[i].w;
} for(int i = ; i<n; i++)
if(i!=root && in[i]==INF)
return -; int tn = ;
memset(id, -, sizeof(id));
memset(vis, -, sizeof(vis));
in[root] = ;
for(int i = ; i<n; i++)
{
res += in[i];
int v = i;
while(vis[v]!=i && id[v]==- && v!=root)
{
vis[v] = i;
v = pre[v];
}
if(v!=root && id[v]==-)
{
for(int u = pre[v]; u!=v; u = pre[u])
id[u] = tn;
id[v] = tn++;
}
}
if(tn==) break;
for(int i = ; i<n; i++)
if(id[i]==-)
id[i] = tn++; for(int i = ; i<m; i++)
{
int 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].w -= in[v];
}
n = tn;
root = id[root];
}
return res;
} int main()
{
int n, m, X, Y, Z;
while(scanf("%d%d%d%d", &n, &X, &Y, &Z)!=EOF)
{
if(!n && !X && !Y && !Z) break; for(int i = ; i<n; i++)
scanf("%d%d%d", &x[i], &y[i], &z[i]); m = ;
for(int i = ; i<n; i++)
{
int num, v;
scanf("%d", &num);
while(num--)
{
scanf("%d", &v); v--;
edge[m].u = i;
edge[m].v = v;
edge[m].w = Y*(abs(x[i]-x[v])+abs(y[i]-y[v])+abs(z[i]-z[v]));
if(z[i]<z[v]) edge[m].w += Z;
m++;
}
//0~n-1为题目中的点, n为人工设置的超级点
//将超级点连到每一个结点,并且设置相应的权值
edge[m].u = n;
edge[m].v = i;
edge[m++].w = z[i]*X;
} int ans = zhuliu(n, n+, m);
printf("%d\n", ans);
}
}

HDU4009 Transfer water —— 最小树形图 + 不定根 + 超级点的更多相关文章

  1. hdu4009 Transfer water 最小树形图

    每一户人家水的来源有两种打井和从别家接水,每户人家都可能向外输送水. 打井和接水两种的付出代价都接边.设一个超级源点,每家每户打井的代价就是从该点(0)到该户人家(1~n)的边的权值.接水有两种可能, ...

  2. HDU2121 Ice_cream’s world II —— 最小树形图 + 不定根 + 超级点

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2121 Ice_cream’s world II Time Limit: 3000/1000 MS (J ...

  3. HDU 4009 Transfer water 最小树形图

    分析:建一个远点,往每个点连建井的价值(单向边),其它输水线按照题意建单向边 然后以源点为根的权值最小的有向树就是答案,套最小树形图模板 #include <iostream> #incl ...

  4. HDOJ 4009 Transfer water 最小树形图

    Transfer water Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) T ...

  5. HDU4009 Transfer water 【最小树形图】

    Transfer water Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) T ...

  6. POJ 3164 Command Network 最小树形图模板

    最小树形图求的是有向图的最小生成树,跟无向图求最小生成树有很大的区别. 步骤大致如下: 1.求除了根节点以外每个节点的最小入边,记录前驱 2.判断除了根节点,是否每个节点都有入边,如果存在没有入边的点 ...

  7. HDU 4009——Transfer water——————【最小树形图、不定根】

    Transfer water Time Limit:3000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64u Subm ...

  8. HDU 4009 Transfer water(最小树形图)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4009 题意:给出一个村庄(x,y,z).每个村庄可以挖井或者修建水渠从其他村庄得到水.挖井有一个代价, ...

  9. 最小树形图(hdu4009)

    Transfer water Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others) T ...

随机推荐

  1. Cannot delete or update a parent row: a foreign key constraint fails....

    在操作”小弟“这张表时候报错 想在“小弟”上面加入数据或者更新数据,就要听老大的, 这句话后面跟着的表就是“老大”,必须老大有数据索引,“小弟“才可以加入或者更新 查看“小弟”表的外键,会发现有对“老 ...

  2. 【转】亿级Web系统搭建——单机到分布式集群

    当一个Web系统从日访问量10万逐步增长到1000万,甚至超过1亿的过程中,Web系统承受的压力会越来越大,在这个过程中,我们会遇到很多的问题.为了解决这些性能压力带来问题,我们需要在Web系统架构层 ...

  3. Selenium加载Chrome/Firefox浏览器配置文件

    Selenium启动浏览器时,默认是打开一个新用户,不会加载原有的配置以及插件.但有些时候我们可能需要加载默认配置. 一.Chrome浏览器 1.在Chrome浏览器的地址栏输入:chrome://v ...

  4. 大数据学习——hdfs客户端操作

    package cn.itcast.hdfs; import org.apache.commons.io.IOUtils; import org.apache.hadoop.conf.Configur ...

  5. 大数据学习——yum安装tomcat

    https://www.cnblogs.com/jtlgb/p/5726161.html 安装tomcat6 yum install tomcat6 tomcat6-webapps tomcat6-a ...

  6. @locked_cached_property ---flask.helpers模块

    源码: class locked_cached_property(object): """A decorator that converts a function int ...

  7. [转载] Asynchronous ActionScript Execution

    Asynchronous ActionScript Execution Date September 19, 2009 Language ActionScript 3.0 Target Flash P ...

  8. python多线程--线程同步

    如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步. 使用Thread对象的Lock和Rlock可以实现简单的线程同步,这两个对象都有acquire ...

  9. Python基础教程笔记——第4章:字典

    字典 字典是Python唯一内建的数学映射类型,字典中的值没有特殊的顺序,键可以是数字,字符串,甚至是元组 字典的创建: 字典由键值对构成,字典中键是唯一的,而值不唯一.>>> a_ ...

  10. Linux下出现launch failed.Binary not found的解决方案

    Linux下出现launch failed.Binary not found的解决方案: Project->Properties->C/C++Build->Settings-> ...