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 ...
随机推荐
- oo第三单元博客作业
JML语言理论基础 Java建模语言(Java Modeling Language,JML)是一种进行详细设计的符号语言,他鼓励你用一种全新的方式来看待Java的类和方法.JML是一种行为接口规格语言 ...
- [luoguP2129] L国的战斗续之多路出击(模拟 || 矩阵)
传送门 1.模拟 easy #include <cstdio> #define N 500001 int n, m; int X[N], Y[N], x[N], y[N], a = 1, ...
- 通过一个用户管理实例学习路由react-router-dom知识
我们通过一个用户管理实例来学习react-router-dom 这个实例包括9个小组件 App.js 引入组件 Home.js 首页组件 User.js 用户管理组件 - UserList.js 用 ...
- Codeforces917D. Stranger Trees
$n \leq 100$的完全图,对每个$0 \leq K \leq n-1$问生成树中与给定的一棵树有$K$条公共边的有多少个,答案$mod \ \ 1e9+7$. 对这种“在整体中求具有某些特性的 ...
- Spring Security教程(5)---- 国际化配置及UserCache
这一章是为了给后面的讲解打基础的,主要介绍下国际化的配置及UserCache的配置及使用 国际化配置 <!-- 定义上下文返回的消息的国际化 --> <bean id="m ...
- MySQL学习系列之触发器
触发器简介 触发器作用: 监控某种事件并触发某种动作 触发语法: CREATE TRIGGER trigger_name trigger_event ON tbl_name FOR EACH ROW ...
- centos7备份还原与grub2引导和rescue模式修改root密码
一.centos7备份1.su -2.cd /3.tar -zpPcvf backup.tgz --exclude=/sys --exclude=/mnt --exclude=/proc --excl ...
- Visual Studio VS如何卸载Visual assistant
1 点击工具-扩展管理器 2 选中Visual Assist X,点击卸载即可.
- SQLite Expert表分离和解决SQLite Expert删除表后大小不变的问题
最后要使用到号码归属地的查询,在网上找到一个数据库文件.大小有12M多,压缩成zip也有1.9M,这样对于一个apk的大小非常不利,后来看了一下数据库的内容,发现有非常多冗余.特别是中文字符占用非常大 ...
- JSP中的编译指令和动作指令的差别
JSP中的编译指令和动作指令的差别 1.编译指令是通知Servlet引擎的处理消息.而动作指令仅仅是执行时的脚本动作 2.编译指令是在将JSP编译成Servlet时起作用,而动作指令可替换成JSP脚本 ...