博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU - 4009 Transfer water(最小树形图)
阅读量:6449 次
发布时间:2019-06-23

本文共 2810 字,大约阅读时间需要 9 分钟。

题目大意:有N个点。每一个点都有对应的三维坐标(x,y,z)

如今要求每一个点都能获得水,或者水的方式有两种
1.自己挖井,费用为X * 海拔高度z
2.铺设管道引水。
a.假设海拔高度小于引水处。费用为两地曼哈顿距离*Y
b.假设海拔高度大于饮水处。费用为两地曼哈顿距离*Y + Z

解题思路:设置一个虚根。虚根引向全部的点,权值为挖井的费用,接着依照要求连边,求出最小树形图就可以

#include 
#include
#define N 1010#define abs(a) ((a)>0?(a):(-(a)))struct Edge{ int u, v, c;}E[N*N];struct Point{ int x, y, z;}P[N];int n, x, y, z, tot;void AddEdge(int u, int v, int c) { E[tot].u = u; E[tot].v = v; E[tot++].c = c;}void init() { tot = 0; for (int i = 1; i <= n; i++) { scanf("%d%d%d", &P[i].x, &P[i].y, &P[i].z); AddEdge(0, i, P[i].z * x); } int k, t; for (int i = 1; i <= n; i++) { scanf("%d", &k); while (k--) { scanf("%d", &t); if (t == i) continue; if (P[i].z >= P[t].z) { int dis = abs(P[t].x - P[i].x) + abs(P[t].y - P[i].y) + abs(P[t].z - P[i].z); AddEdge(i, t, dis * y); } else { int dis = abs(P[t].x - P[i].x) + abs(P[t].y - P[i].y) + abs(P[t].z - P[i].z); AddEdge(i, t, dis * y + z); } } }}#define INF 0x3f3f3f3fint in[N], pre[N], vis[N], id[N];int Directed_MST(int root, int n) { int ans = 0, u, v, tmp; while (1) { for (int i = 0; i < n; i++) in[i] = INF; for (int i = 0; i < tot; i++) { u = E[i].u; v = E[i].v; if (u != v && E[i].c < in[v]) { in[v] = E[i].c; pre[v] = u; } } memset(vis, -1, sizeof(vis)); memset(id, -1, sizeof(id)); in[root] = 0; int subnode = 0; for (int i = 0; i < n; i++) { ans += in[i]; tmp = i; while (vis[tmp] != i && tmp != root && id[tmp] == -1) { vis[tmp] = i; tmp = pre[tmp]; } if (id[tmp] == -1 && tmp != root) { u = pre[tmp]; while (u != tmp) { id[u] = subnode; u = pre[u]; } id[tmp] = subnode++; } } if (subnode == 0) break; for (int i = 0; i < n; i++) if (!(~id[i])) id[i] = subnode++; for (int i = 0; i < tot; i++) { tmp = E[i].v; E[i].u = id[E[i].u]; E[i].v = id[E[i].v]; if (E[i].u != E[i].v) E[i].c -= in[tmp]; } n = subnode; root = id[root]; } return ans;}void solve() { n++; int ans = Directed_MST(0,n); if (ans == -1) printf("poor XiaoA\n"); else printf("%d\n", ans);}int main() { while (scanf("%d%d%d%d", &n, &x, &y, &z) != EOF && n + x + y + z) { init(); solve(); } return 0;}

转载地址:http://kylwo.baihongyu.com/

你可能感兴趣的文章
10. Regular Expression Matching
查看>>
C# 实现天气预报
查看>>
ios中键盘处理(二)
查看>>
从1.5k到18k, 一个程序员的5年成长之路
查看>>
poj 3013 SPFA
查看>>
QT与opencv(二)开启摄像头
查看>>
解惑 和 遇到的问题
查看>>
http协议之实践巩固(深度篇一)
查看>>
高级网络营销师黄杰告诉你:SEM的取舍之道
查看>>
隐藏控制台窗口的方法
查看>>
【转】Linux下svn常用指令
查看>>
test
查看>>
前端学习网站推荐
查看>>
Windows Phone 获取网络类型(GSM/CDMA/WIFI/Ethernet)
查看>>
006、容器 What、Why、How(2018-12-21 周五)
查看>>
LeetCode算法题-Linked List Cycle(Java实现)
查看>>
nlp Task1
查看>>
基于reflectasm打造自己的通用bean工具
查看>>
ReactiveCocoa & MVVM 学习总结一
查看>>
MVVM
查看>>