热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

hdu4009Transferwater有固定根的最小树形图

ProblemDescriptionXiaoAlivesinavillage.Lastyearfloodrainedthevillage

Problem Description
XiaoA lives in a village. Last year flood rained the village. So they decide to move the whole village to the mountain nearby this year. There is no spring in the mountain, so each household could only dig a well or build a water line from other household. If the household decide to dig a well, the money for the well is the height of their house multiplies X dollar per meter. If the household decide to build a water line from other household, and if the height of which supply water is not lower than the one which get water, the money of one water line is the Manhattan distance of the two households multiplies Y dollar per meter. Or if the height of which supply water is lower than the one which get water, a water pump is needed except the water line. Z dollar should be paid for one water pump. In addition,therelation of the households must be considered. Some households may do not allow some other households build a water line from there house. Now given the 3‐dimensional position (a, b, c) of every household the c of which means height, can you calculate the minimal money the whole village need so that every household has water, or tell the leader if it can’t be done.
 

Input
Multiple cases. 
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. 
 

Output
One integer in one line for each case, the minimal money the whole village need so that every household has water. If the plan does not exist, print “poor XiaoA” in one line. 
 

Sample Input
 
  
2 10 20 30 1 3 2 2 4 1 1 2 2 1 2 0 0 0 0
 

Sample Output
 
  
30
Hint
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
#include
#include
#include
#include
using namespace std;
const int maxn = 1501;
const int TOOBIG = (1<<30);
//1是固定根
/*
 if(!min_shuxingtu()) puts("impossible");
else{
    printf("%.0lf\n",ans);
}
*/
//不能将!=-1改成>0,==-1改成<0
double g[maxn][maxn], mincost[maxn];
int pre[maxn], n;
bool vis[maxn], exist[maxn];
double  ans;


void combine(int *list, int h, int r) {
    // 环中的点依序保存在 list[h..r] 中,将这个环缩成一个点
    memset(vis, 0, sizeof(vis));
    for (int i = h; i <= r; i++) {
        vis[list[i]] = true;
        exist[list[i]] = false;
    }
    int now = list[h];
    // 首先处理边权问题
    double newg[maxn];
    for (int j = 1; j <= n; j++) newg[j] = TOOBIG;
    for (int i = h; i <= r; i++) {
        int x = list[i];
        ans += mincost[x];
        for (int j = 1; j <= n; j++) if (!vis[j] && exist[j]) {
            if (g[j][x] != -1) {
                double tmp = g[j][x] - mincost[x];
                newg[j] = min(newg[j], tmp);
            }
            if ((g[x][j] != -1 && g[x][j]         }
    }
    exist[now] = true;
    for (int j = 1; j <= n; j++) g[j][now] = newg[j];
    // 然后处理缩成的点引出的最小边
    for (int i = 2; i <= n; i++) if (exist[i] && !vis[i] && vis[pre[i]]) pre[i] = now;
    // 最后处理缩成的点自己的最小边
    mincost[now] = TOOBIG;
    for (int i = 1; i <= n; i++)
        if (exist[i] && i != now && g[i][now] != -1 && g[i][now]             mincost[now] = g[i][now];
            pre[now] = i;
        }
}


bool find_circle(int *list, int &h, int &r) {
    // 由于每个点的 vis 只会被标记一次,所以这个过程是 O(n) 的
    // 如果找到了环那么将环中的点依序保存在 list[h..r] 中
    int mark[maxn];
    memset(vis, 0, sizeof(vis));
    for (int k = 2; k <= n; k++) if (!vis[k] && exist[k]) {
        memset(mark, 0, sizeof(mark));
        r = 0;
        int i = k;
        for (; i != 1 && !mark[i] && !vis[i]; i = pre[i]) {
            vis[i] = true;
            r++;
            list[r] = i;
            mark[i] = r;
        }
        if (mark[i]) {
            h = mark[i];
            return true;
        }
    }
    return false;
}


void dfs(int v){
    vis[v] = true;
    for (int i = 1; i <= n; i++) if (!vis[i] && g[v][i] != -1) dfs(i);
}


bool min_shuxingtu() {
    // 求以 1 为根的最小树形图,原图以邻接矩阵保存于 g[1..n][1..n] 中,求解将破坏 g 矩阵
    // 如果存在返回 true,并且将最小树形图的边权和放在 ans 中,否则返回 false
    memset(vis, 0, sizeof(vis));
    dfs(1);
    for (int i = 1; i <= n; i++) if (!vis[i]) return false;
    // 初始化 mincost 和 pre 和 id
    for (int i = 1; i <= n; i++) exist[i] = true;
    for (int i = 2; i <= n; i++) {
        mincost[i] = TOOBIG;
        for (int j = 1; j <= n; j++)
            if (j != i && g[j][i] != -1 && g[j][i]                 mincost[i] = g[j][i];
                pre[i] = j;
            }
    }
    ans = 0;
    int list[maxn], h, r;
    while (find_circle(list, h, r)) combine(list, h, r);
    for (int i = 2; i <= n; i++) if (exist[i]) ans += mincost[i];
    return true;
}


int ha[2000], hb[2000], hc[2000];
int x, y, z;


int abs(int x){ return (x <0 ? -x : x); }


int dist(int i, int j){
    int ret = abs(ha[i] - ha[j]) + abs(hb[i] - hb[j]) + abs(hc[i] - hc[j]);
    ret *= y;
    if (hc[i]     return ret;
}




int main() {
    while(scanf("%d%d%d%d",&n,&x,&y,&z)==4&&n) {
        n++;
        for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) g[i][j]=-1;
        for (int i = 2; i <= n; i++) scanf("%d %d %d", &ha[i], &hb[i], &hc[i]);
        for (int i = 2; i <= n; i++) {
            g[1][i] = hc[i]*x;
            int k;
            scanf("%d", &k);
            while (k--) {
                int j;
                scanf("%d", &j);
                j++;
                if (j != i) {
                    int c = dist(i, j);
                    //if(g[i][j] == -1 || g[i][j] > c) g[i][j] = c;
                    g[i][j]=c;
                }
            }
        }
        if (!min_shuxingtu()) puts("Impossible");
        else printf("%.0lf\n",ans);
    }
    return 0;
}
//对于不固定根的最小树形图,新加一个点,和每个点连权相同的边,
//这个权大于原图所有边权的和,这样这个图固定跟的最小树形图和原图
//不固定跟的最小树形图就是对应的了。


推荐阅读
  • [线段树|平衡树|树状数组]LightOJ - 1087 - Diablo
    1087-DiabloPDF(English)StatisticsForum ... [详细]
  • fzu 1715 Ball and Box n个不同的求放到m个不同的盒子中方法的个数
    1715BallandBoxAccept:120Submit:288TimeLimit:1000mSecMemoryLimit:32768KBProblem ... [详细]
  • 深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案
    深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案 ... [详细]
  • 题目要求维护一个数列,并支持两种操作:一是查询操作,语法为QL,用于查询数列末尾L个数中的最大值;二是更新操作,用于修改数列中的某个元素。本文通过ST表(Sparse Table)优化查询效率,确保在O(1)时间内完成查询,同时保持较低的预处理时间复杂度。 ... [详细]
  • 在处理 XML 数据时,如果需要解析 `` 标签的内容,可以采用 Pull 解析方法。Pull 解析是一种高效的 XML 解析方式,适用于流式数据处理。具体实现中,可以通过 Java 的 `XmlPullParser` 或其他类似的库来逐步读取和解析 XML 文档中的 `` 元素。这样不仅能够提高解析效率,还能减少内存占用。本文将详细介绍如何使用 Pull 解析方法来提取 `` 标签的内容,并提供一个示例代码,帮助开发者快速解决问题。 ... [详细]
  • 本文探讨了如何利用Java代码获取当前本地操作系统中正在运行的进程列表及其详细信息。通过引入必要的包和类,开发者可以轻松地实现这一功能,为系统监控和管理提供有力支持。示例代码展示了具体实现方法,适用于需要了解系统进程状态的开发人员。 ... [详细]
  • oracle c3p0 dword 60,web_day10 dbcp c3p0 dbutils
    createdatabasemydbcharactersetutf8;alertdatabasemydbcharactersetutf8;1.自定义连接池为了不去经常创建连接和释放 ... [详细]
  • poj 3352 Road Construction ... [详细]
  • 在软件开发过程中,经常需要将多个项目或模块进行集成和调试,尤其是当项目依赖于第三方开源库(如Cordova、CocoaPods)时。本文介绍了如何在Xcode中高效地进行多项目联合调试,分享了一些实用的技巧和最佳实践,帮助开发者解决常见的调试难题,提高开发效率。 ... [详细]
  • 本项目通过Python编程实现了一个简单的汇率转换器v1.02。主要内容包括:1. Python的基本语法元素:(1)缩进:用于表示代码的层次结构,是Python中定义程序框架的唯一方式;(2)注释:提供开发者说明信息,不参与实际运行,通常每个代码块添加一个注释;(3)常量和变量:用于存储和操作数据,是程序执行过程中的重要组成部分。此外,项目还涉及了函数定义、用户输入处理和异常捕获等高级特性,以确保程序的健壮性和易用性。 ... [详细]
  • 属性类 `Properties` 是 `Hashtable` 类的子类,用于存储键值对形式的数据。该类在 Java 中广泛应用于配置文件的读取与写入,支持字符串类型的键和值。通过 `Properties` 类,开发者可以方便地进行配置信息的管理,确保应用程序的灵活性和可维护性。此外,`Properties` 类还提供了加载和保存属性文件的方法,使其在实际开发中具有较高的实用价值。 ... [详细]
  • 本文全面解析了 Python 中字符串处理的常用操作与技巧。首先介绍了如何通过 `s.strip()`, `s.lstrip()` 和 `s.rstrip()` 方法去除字符串中的空格和特殊符号。接着,详细讲解了字符串复制的方法,包括使用 `sStr1 = sStr2` 进行简单的赋值复制。此外,还探讨了字符串连接、分割、替换等高级操作,并提供了丰富的示例代码,帮助读者深入理解和掌握这些实用技巧。 ... [详细]
  • 在Cisco IOS XR系统中,存在提供服务的服务器和使用这些服务的客户端。本文深入探讨了进程与线程状态转换机制,分析了其在系统性能优化中的关键作用,并提出了改进措施,以提高系统的响应速度和资源利用率。通过详细研究状态转换的各个环节,本文为开发人员和系统管理员提供了实用的指导,旨在提升整体系统效率和稳定性。 ... [详细]
  • 本文深入解析了WCF Binding模型中的绑定元素,详细介绍了信道、信道管理器、信道监听器和信道工厂的概念与作用。从对象创建的角度来看,信道管理器负责信道的生成。具体而言,客户端的信道通过信道工厂进行实例化,而服务端则通过信道监听器来接收请求。文章还探讨了这些组件之间的交互机制及其在WCF通信中的重要性。 ... [详细]
  • POJ 2482 星空中的星星:利用线段树与扫描线算法解决
    在《POJ 2482 星空中的星星》问题中,通过运用线段树和扫描线算法,可以高效地解决星星在窗口内的计数问题。该方法不仅能够快速处理大规模数据,还能确保时间复杂度的最优性,适用于各种复杂的星空模拟场景。 ... [详细]
author-avatar
xinzhugedonny
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有