zoukankan      html  css  js  c++  java
  • hdu 4009 Transfer water(最小树形图生成森林)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4009

      再来最小树形图的题,拿来练习打最小树形图的朱刘算法.....

      这题看懂了以后想不到办法解决,于是就喵了喵别人的代码,才发现原来不仅网络流的构图要技巧,最小树形图的、解决也需要技巧的。这让我大开眼界了!

      这题的构图跟不定根的构图差不多,不过这里可以有多个根,也就是要求有向图的最小生成森林了。看上去还有点像网络流,不过好像不能用网络流来解决。

      看懂了构图以后,就唯有将这题当作是练手了,剩下的就是体力活儿了.....最小树形图的代码挺多陷阱的,尤其要注意寻找环那部分的代码,因为那里比较容易打错变量。另外还有环的判定条件,写漏了也会产生巨大的影响!最后就是更新边,以及找最小边权的时候要注意判起点和终点是否相同。

      下面是这题的代码,运行速度挺快的,890ms,内存消耗也相当小,5MB!

    View Code
      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <cmath>
      5 
      6 typedef __int64 ll;
      7 const int inf = 0x7f7f7f7f;
      8 const int maxn = 1001;
      9 
     10 struct edge{
     11     int s, t;
     12     int c;
     13     void add(int a, int b, int cost){
     14         s = a;
     15         t = b;
     16         c = cost;
     17     }
     18 }E[maxn * maxn];
     19 struct point{
     20     int x, y, z;
     21     int operator - (const point &a) {
     22         return abs(x - a.x) + abs(y - a.y) + abs(z - a.z);
     23     }
     24 }P[maxn];
     25 int min_cost;
     26 int vis[maxn], fold[maxn], cost[maxn], pre[maxn];
     27 
     28 bool make_tree(int root, int v, int e){
     29     int i, j, k, cnt;
     30     int s, t;
     31 
     32     min_cost = 0;
     33     while (true){
     34         for (i = 0; i < v; i++){
     35             cost[i] = inf;
     36         }
     37         for (i = 0; i < e; i++){
     38             s = E[i].s;
     39             t = E[i].t;
     40 
     41             if (cost[t] > E[i].c && s != t){
     42                 cost[t] = E[i].c;
     43                 pre[t] = s;
     44             }
     45         } // find min-arc
     46 
     47         cost[root] = 0;
     48         for (i = 0; i < v; i++){
     49             min_cost += cost[i];
     50             vis[i] = fold[i] = -1;
     51             if (cost[i] == inf && i != root) return false;
     52         } // whether it can be built
     53 
     54         cnt = 0;
     55         for (i = 0; i < v; i++){
     56             j = i;
     57             for (vis[j] = i, j = pre[j]; vis[j] != i && fold[j] == -1 && j != root; vis[j] = i, j = pre[j]);
     58 
     59             if (fold[j] != -1 || j == root) continue;
     60             k = j;
     61             for (fold[k] = cnt, k = pre[k]; k != j; fold[k] = cnt, k = pre[k]);
     62             cnt++;
     63         } // find circle
     64 
     65         if (!cnt) return true; // no circle, tree built
     66 
     67         for (i = 0; i < v; i++){
     68             if (fold[i] == -1) fold[i] = cnt++;
     69         } // re-number vexs
     70 
     71         for (i = 0; i < e; i++){
     72             s = E[i].s;
     73             t = E[i].t;
     74 
     75             E[i].s = fold[s];
     76             E[i].t = fold[t];
     77             if (E[i].s != E[i].t){
     78                 E[i].c -= cost[t];
     79             }
     80         } // refresh arcs
     81         v = cnt;
     82         root = fold[root];
     83     }
     84 }
     85 
     86 
     87 
     88 
     89 
     90 
     91 bool deal(){
     92     int n, X, Y, Z;
     93     int k, m = 0, r;
     94 
     95     scanf("%d%d%d%d", &n, &X, &Y, &Z);
     96     if (!n && !X && !Y && !Z) return false;
     97 
     98     for (int i = 1; i <= n; i++){
     99         scanf("%d%d%d", &P[i].x, &P[i].y, &P[i].z);
    100         E[m].add(0, i, P[i].z * X);
    101         m++;
    102     }
    103     for (int i = 1; i <= n; i++){
    104         scanf("%d", &k);
    105         while (k--){
    106             scanf("%d", &r);
    107             if (r != i){
    108                 if (P[i].z >= P[r].z) E[m].add(i, r, (P[i] - P[r]) * Y);
    109                 else E[m].add(i, r, (P[i] - P[r]) * Y + Z);
    110                 m++;
    111             }
    112         }
    113     }
    114 
    115     if (make_tree(0, n + 1, m)) printf("%d\n", min_cost);
    116     else puts("poor XiaoA");
    117 
    118     return true;
    119 }
    120 
    121 int main(){
    122     #ifndef ONLINE_JUDGE
    123     freopen("in", "r", stdin);
    124     #endif
    125     while (deal());
    126 
    127     return 0;
    128 }

      最小树形图就先练这几题。模板测试通过,以后能放心用了~

    ——written by Lyon

  • 相关阅读:
    移动网络介绍
    统一导航路由方案
    负载均衡汇总
    Openfire部署和配置说明
    CDN技术介绍
    流媒体
    WebSocket和HTTP的区别与联系
    zabbix 邮件报警
    Linux系统故障-Repair filesystem
    redhat 6.8 配置yum源
  • 原文地址:https://www.cnblogs.com/LyonLys/p/hdu_4009_Lyon.html
Copyright © 2011-2022 走看看