HDU4009 Transfer water —— 最小树形图 + 不定根 + 超级点
题目链接: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
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.
1 3 2
2 4 1
1 2
2 1 2
0 0 0 0
In 3‐dimensional space Manhattan distance of point A (x1, y1, z1) and B(x2, y2, z2) is |x2‐x1|+|y2‐y1|+|z2‐z1|.
代码一:
#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 —— 最小树形图 + 不定根 + 超级点的更多相关文章
- hdu4009 Transfer water 最小树形图
每一户人家水的来源有两种打井和从别家接水,每户人家都可能向外输送水. 打井和接水两种的付出代价都接边.设一个超级源点,每家每户打井的代价就是从该点(0)到该户人家(1~n)的边的权值.接水有两种可能, ...
- 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 ...
- HDU 4009 Transfer water 最小树形图
分析:建一个远点,往每个点连建井的价值(单向边),其它输水线按照题意建单向边 然后以源点为根的权值最小的有向树就是答案,套最小树形图模板 #include <iostream> #incl ...
- HDOJ 4009 Transfer water 最小树形图
Transfer water Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others) T ...
- HDU4009 Transfer water 【最小树形图】
Transfer water Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others) T ...
- POJ 3164 Command Network 最小树形图模板
最小树形图求的是有向图的最小生成树,跟无向图求最小生成树有很大的区别. 步骤大致如下: 1.求除了根节点以外每个节点的最小入边,记录前驱 2.判断除了根节点,是否每个节点都有入边,如果存在没有入边的点 ...
- HDU 4009——Transfer water——————【最小树形图、不定根】
Transfer water Time Limit:3000MS Memory Limit:65768KB 64bit IO Format:%I64d & %I64u Subm ...
- HDU 4009 Transfer water(最小树形图)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4009 题意:给出一个村庄(x,y,z).每个村庄可以挖井或者修建水渠从其他村庄得到水.挖井有一个代价, ...
- 最小树形图(hdu4009)
Transfer water Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others) T ...
随机推荐
- iptables工具
http://www.linuxidc.com/Linux/2012-12/77074.htm iptables 指令 语法: iptables [-t table] command [match] ...
- Shell脚本问题详解
例1:找出当前系统中端口大于1024的程序! 使用netstat -tuln查询出的结果如下,需要输出红色字体的行: [root@localhost ~]# netstat -tuln Active ...
- mybatis自动映射和手动映射
一对一查询 第一种方法: <!-- 查询所有订单信息 --> <select id="findOrdersList" resultType="cn.it ...
- 收集整理Android开发所需的Android SDK、开发中用到的工具、Android开发教程、Android设计规范,免费的设计素材等。
AndroidDevTools Android Dev Tools官网地址:www.androiddevtools.cn 收集整理Android开发所需的Android SDK.开发中用到的工具.An ...
- RQNOJ273 马棚问题
题目描述 每天,小明和他的马外出,然后他们一边跑一边玩耍.当他们结束的时候,必须带所有的马返回马棚,小明有K个马棚.他把他的马排成一排然后跟随它走向马棚,因为他们非常疲劳,小明不想让他的马做过多的移动 ...
- 怎么配置ODBC microsoft Access 安装(win10)
笔者看着书配置Access连接方法但就是找不到书中的"Access.mdb". 后来才知道.mdb需要自己创建....对于刚入门的我很无语啊!!!!! 下面带你走出小坑 1.从控制 ...
- spring/spring boot/spring mvc中用到的注解
在spring Boot中几乎可以完全弃用xml配置文件,本文的主题是分析常用的注解. Spring最开始是为了解决EJB等大型企业框架对应用程序的侵入性,因此大量依靠配置文件来“非侵入式”得给POJ ...
- 从头开始学Android之(二)—— Android版本
前面大致的介绍了一下Android的Linux内核层,知道Android是Google在Linux基础上创建的一个应用于移动设备的系统,并在针对移动设备的特殊性,在Linux上做了一些相应的改动建立起 ...
- Reload file in vim
68down voteaccepted Give this a try: :e From :h :e: Edit the current file. This is useful to re-edit ...
- volatile关键字解析&内存模型&并发编程中三概念
原文链接: http://www.cnblogs.com/dolphin0520/p/3920373.html volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java5之前,它是一个 ...