[HDU 4009] Transfer water 最小树形图
2015-08-12 19:45
423 查看
http://acm.hdu.edu.cn/showproblem.php?pid=4009
题意:有n个地方需要供水,每个地方都可以选择是自己挖井,还是从别的地方引水,根据方法不同和每个地方的坐标不同,花费也不同,现在给出每个地方的坐标,花费的计算方法,以及每个地方可以给哪些地方供水,求给所有地方供水的最小花费。
思路:建立一个源点,到每个点到源点的距离为自己打井的费用,其他的按条件建边。
题意:有n个地方需要供水,每个地方都可以选择是自己挖井,还是从别的地方引水,根据方法不同和每个地方的坐标不同,花费也不同,现在给出每个地方的坐标,花费的计算方法,以及每个地方可以给哪些地方供水,求给所有地方供水的最小花费。
思路:建立一个源点,到每个点到源点的距离为自己打井的费用,其他的按条件建边。
[code]#include <cmath> #include <cstdio> #include <cstring> #include <iostream> using namespace std; const int maxn = 1010; const int inf = (1 << 31) - 1; struct Point{ int x, y, z; }; struct node { int value; int in, to; node(int a = 0, int b = 0, int c = 0){ in = a; to = b; value = c; } }; int cnt; int in[maxn]; Point point[maxn]; node side[1010000]; int pre[maxn], id[maxn], vis[maxn]; int Mst(int rt, int n, int m) { int sum = 0; while(true){ for(int i = 0; i < n; i++){ in[i] = inf; } for(int i = 0; i < m; i++) //找最小入边 { int x = side[i].to; if(in[x] > side[i].value && x != side[i].in){ in[x] = side[i].value; pre[x] = side[i].in; } } for(int i = 0; i < n; i++){ //判断除了根是否还有其他入度为0的点 if(i != rt && in[i] == inf) //不存在 return -1; } cnt = in[rt] = 0; memset(id, -1, sizeof(id)); memset(vis, -1, sizeof(vis)); for(int i = 0; i < n; i++){ sum += in[i]; int x = i; while(vis[x] != i && x != rt && id[x] == -1){ //找环 vis[x] = i; x = pre[x]; } if(id[x] == -1 && x != rt){ int y = pre[x]; while(x != y){ //给环重新编号 id[y] = cnt; y = pre[y]; } id[x] = cnt++; } } if(cnt == 0) break; for(int i = 0; i < n; i++){ if(id[i] == -1) id[i] = cnt++; } for(int i = 0; i < m; i++){ //压环成点 int x = side[i].to; side[i].in = id[side[i].in]; side[i].to = id[side[i].to]; if(side[i].in != side[i].to) side[i].value -= in[x]; } n = cnt; rt = id[rt]; } return sum; } int length(Point a, Point b) { return abs(a.x - b.x) + abs(a.y - b.y) + abs(a.z - b.z); } int main() { int n, x, y, z; while(~scanf("%d%d%d%d",&n,&x,&y,&z) && (n || x || y || z)) { int top = 0; for(int i = 1 ;i <= n;i++) { scanf("%d%d%d",&point[i].x, &point[i].y, &point[i].z); side[top++] = node(0, i, x * point[i].z); } int k, w; for(int i = 1; i <= n; i++) { scanf("%d", &k); while(k--){ scanf("%d", &w); if(i == w) continue; int len = length(point[i], point[w]); if(point[i].z >= point[w].z) side[top++] = node(i, w, len * y); else side[top++] = node(i, w, len * y + z); } } printf("%d\n", Mst(0, n+1, top)); } return 0; }
相关文章推荐
- 【 D3.js 入门系列 --- 9.6 】 生产的包图
- MySQL 打开federated存储引擎
- ajax.js
- 【实例】html5-canvas通过鼠标绘制线段
- JavaScript去除字符串两边空格trim
- Js学习第十天----函数
- HTMl小知识
- JavaScript跨域总结与解决办法
- JSON-C结构简介、使用
- html学习笔记(8)
- html5 video标签不能播放mp4的问题
- IE 兼容模式下不支持DIV CSS样式display:inline-block,解决
- *+html功能
- 详解CSS中视窗单位和百分比单位的使用
- css写三角形
- CSS里面逗号和分号的区别
- js实现自定义滚动条
- jQuery Validation remote的缓存请求
- CSS中的下划线text-decoration属性使用进阶
- 浅谈 JavaScript DDoS 攻击原理与防御