hdu 4009 Transfer water(最小树形图生成森林)
2012-08-11 01:31
411 查看
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4009
再来最小树形图的题,拿来练习打最小树形图的朱刘算法.....
这题看懂了以后想不到办法解决,于是就喵了喵别人的代码,才发现原来不仅网络流的构图要技巧,最小树形图的、解决也需要技巧的。这让我大开眼界了!
这题的构图跟不定根的构图差不多,不过这里可以有多个根,也就是要求有向图的最小生成森林了。看上去还有点像网络流,不过好像不能用网络流来解决。
看懂了构图以后,就唯有将这题当作是练手了,剩下的就是体力活儿了.....最小树形图的代码挺多陷阱的,尤其要注意寻找环那部分的代码,因为那里比较容易打错变量。另外还有环的判定条件,写漏了也会产生巨大的影响!最后就是更新边,以及找最小边权的时候要注意判起点和终点是否相同。
下面是这题的代码,运行速度挺快的,890ms,内存消耗也相当小,5MB!
View Code
最小树形图就先练这几题。模板测试通过,以后能放心用了~
——written by Lyon
再来最小树形图的题,拿来练习打最小树形图的朱刘算法.....
这题看懂了以后想不到办法解决,于是就喵了喵别人的代码,才发现原来不仅网络流的构图要技巧,最小树形图的、解决也需要技巧的。这让我大开眼界了!
这题的构图跟不定根的构图差不多,不过这里可以有多个根,也就是要求有向图的最小生成森林了。看上去还有点像网络流,不过好像不能用网络流来解决。
看懂了构图以后,就唯有将这题当作是练手了,剩下的就是体力活儿了.....最小树形图的代码挺多陷阱的,尤其要注意寻找环那部分的代码,因为那里比较容易打错变量。另外还有环的判定条件,写漏了也会产生巨大的影响!最后就是更新边,以及找最小边权的时候要注意判起点和终点是否相同。
下面是这题的代码,运行速度挺快的,890ms,内存消耗也相当小,5MB!
View Code
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> typedef __int64 ll; const int inf = 0x7f7f7f7f; const int maxn = 1001; struct edge{ int s, t; int c; void add(int a, int b, int cost){ s = a; t = b; c = cost; } }E[maxn * maxn]; struct point{ int x, y, z; int operator - (const point &a) { return abs(x - a.x) + abs(y - a.y) + abs(z - a.z); } }P[maxn]; int min_cost; int vis[maxn], fold[maxn], cost[maxn], pre[maxn]; bool make_tree(int root, int v, int e){ int i, j, k, cnt; int s, t; min_cost = 0; while (true){ for (i = 0; i < v; i++){ cost[i] = inf; } for (i = 0; i < e; i++){ s = E[i].s; t = E[i].t; if (cost[t] > E[i].c && s != t){ cost[t] = E[i].c; pre[t] = s; } } // find min-arc cost[root] = 0; for (i = 0; i < v; i++){ min_cost += cost[i]; vis[i] = fold[i] = -1; if (cost[i] == inf && i != root) return false; } // whether it can be built cnt = 0; for (i = 0; i < v; i++){ j = i; for (vis[j] = i, j = pre[j]; vis[j] != i && fold[j] == -1 && j != root; vis[j] = i, j = pre[j]); if (fold[j] != -1 || j == root) continue; k = j; for (fold[k] = cnt, k = pre[k]; k != j; fold[k] = cnt, k = pre[k]); cnt++; } // find circle if (!cnt) return true; // no circle, tree built for (i = 0; i < v; i++){ if (fold[i] == -1) fold[i] = cnt++; } // re-number vexs for (i = 0; i < e; i++){ s = E[i].s; t = E[i].t; E[i].s = fold[s]; E[i].t = fold[t]; if (E[i].s != E[i].t){ E[i].c -= cost[t]; } } // refresh arcs v = cnt; root = fold[root]; } } bool deal(){ int n, X, Y, Z; int k, m = 0, r; scanf("%d%d%d%d", &n, &X, &Y, &Z); if (!n && !X && !Y && !Z) return false; for (int i = 1; i <= n; i++){ scanf("%d%d%d", &P[i].x, &P[i].y, &P[i].z); E[m].add(0, i, P[i].z * X); m++; } for (int i = 1; i <= n; i++){ scanf("%d", &k); while (k--){ scanf("%d", &r); if (r != i){ if (P[i].z >= P[r].z) E[m].add(i, r, (P[i] - P[r]) * Y); else E[m].add(i, r, (P[i] - P[r]) * Y + Z); m++; } } } if (make_tree(0, n + 1, m)) printf("%d\n", min_cost); else puts("poor XiaoA"); return true; } int main(){ #ifndef ONLINE_JUDGE freopen("in", "r", stdin); #endif while (deal()); return 0; }
最小树形图就先练这几题。模板测试通过,以后能放心用了~
——written by Lyon
相关文章推荐
- hdu 4009 Transfer water(最小树形图:有向图的最小生成树模板)
- HDU 4009 Transfer water 最小树形图
- Hdu 4009 Transfer water(最小树形图)
- HDU 4009 Transfer water(最小树形图)
- [HDU 4009] Transfer water 最小树形图
- HDU - 4009 Transfer water(最小树形图)
- HDU -- 4009 Transfer water 【无定根的最小树形图 + 思维】
- hdu 4009 Transfer water(无固定根最小树形图)
- Hdu 4009 Transfer water (最小树形图)
- HDU 4009 Transfer water(最小树形图)
- HDU 4009 Transfer water 最小树形图
- HDU - 4009 Transfer water(最小树形图)
- HDU 4009 Transfer water 朱刘算法求无固定根最小树形图
- HDU - 4009-Transfer water (最小树形图)
- Transfer water - HDU 4009 - 最小树形图
- HDU 4009 Transfer water(最小树形图)
- hdu 4009 Transfer water 最小树形图
- HDU 4009 Transfer water 最小树形图 朱刘算法
- HDU 4009 Transfer water【最小树形图】
- HDU 4009 Transfer water 最小树形图(简单题)