问题描述

  栋栋居住在一个繁华的C市中,然而,这个城市的道路大都年久失修。市长准备重新修一些路以方便市民,于是找到了栋栋,希望栋栋能帮助他。

C市中有n个比较重要的地点,市长希望这些地点重点被考虑。现在可以修一些道路来连接其中的一些地点,每条道路可以连接其中的两个地点。另外由于C市有一条河从中穿过,也可以在其中的一些地点建设码头,所有建了码头的地点可以通过河道连接。

栋栋拿到了允许建设的道路的信息,包括每条可以建设的道路的花费,以及哪些地点可以建设码头和建设码头的花费。

市长希望栋栋给出一个方案,使得任意两个地点能只通过新修的路或者河道互达,同时花费尽量小。

输入格式

  输入的第一行包含两个整数n, m,分别表示C市中重要地点的个数和可以建设的道路条数。所有地点从1到n依次编号。

  接下来m行,每行三个整数a, b, c,表示可以建设一条从地点a到地点b的道路,花费为c。若c为正,表示建设是花钱的,如果c为负,则表示建设了道路后还可以赚钱(比如建设收费道路)。

  接下来一行,包含n个整数w_1, w_2, …, w_n。如果w_i为正数,则表示在地点i建设码头的花费,如果w_i为-1,则表示地点i无法建设码头。

  输入保证至少存在一个方法使得任意两个地点能只通过新修的路或者河道互达。

输出格式

  输出一行,包含一个整数,表示使得所有地点通过新修道路或者码头连接的最小花费。如果满足条件的情况下还能赚钱,那么你应该输出一个负数。

样例输入

5 5

1 2 4

1 3 -1

2 3 3

2 4 5

4 5 10

-1 10 10 1 1

样例输出

9

样例说明

  建设第2、3、4条道路,在地点4、5建设码头,总的花费为9。

数据规模和约定

  对于20%的数据,1<=n<=10,1<=m<=20,0<=c<=20,w_i<=20;

  对于50%的数据,1<=n<=100,1<=m<=1000,-50<=c<=50,w_i<=50;

  对于70%的数据,1<=n<=1000;

  对于100%的数据,1 <= n <= 10000,1 <= m <= 100000,-1000<=c<=1000,-1<=w_i<=1000,w_i≠0。




此题主要考查Kruskal算法的运用,对于本题包含码头部分需要加一个状态顶点0与相应顶点连接,表示一条边。

注意:此处不单单是求最小生成树,其中权值为负数的边均要修,因为修这条边是百分之百赚钱的,在赚钱的基础上再求取最小生成树,确定每两个顶点均连通。

求取最小生成树时考虑两点:

(1)仅仅只有道路,此时共包含顶点1~n个顶点,顶点个数为n;

(2)包含码头,此处加一个额外状态顶点0,即顶点个数为n + 1,此时要特别注意码头最低要两个才有用,即包含顶点0的边最少要有两条。

  1. import java.util.ArrayList;
  2. import java.util.Collections;
  3. import java.util.Comparator;
  4. import java.util.Scanner;
  5. public class Main {
  6. public static int n, m;
  7. public static int[] id;
  8. public static ArrayList<edge> list = new ArrayList<edge>();
  9. public static int result = Integer.MAX_VALUE;
  10. static class edge {
  11. public int a;
  12. public int b;
  13. public int value;
  14. public edge(int a, int b, int value) {
  15. this.a = a;
  16. this.b = b;
  17. this.value = value;
  18. }
  19. }
  20. class MyComparator implements Comparator<edge> {
  21. public int compare(edge o1, edge o2) {
  22. if(o1.value > o2.value)
  23. return 1;
  24. else if(o1.value < o2.value)
  25. return -1;
  26. return 0;
  27. }
  28. }
  29. public int find(int a) {
  30. int root = a;
  31. while(id[root] >= 0) {
  32. root = id[root];
  33. }
  34. int i = 0, k = a;
  35. while(k != root) {
  36. i = id[k];
  37. id[k] = root;
  38. k = i;
  39. }
  40. return root;
  41. }
  42. public void union(int a, int b) {
  43. int rootA = find(a);
  44. int rootB = find(b);
  45. if(rootA == rootB)
  46. return;
  47. int num = id[rootA] + id[rootB];
  48. if(id[rootA] < id[rootB]) {
  49. id[rootB] = rootA;
  50. id[rootA] = num;
  51. } else {
  52. id[rootA] = rootB;
  53. id[rootB] = num;
  54. }
  55. }
  56. public void kruskal() {
  57. Collections.sort(list, new MyComparator());
  58. int temp = 0;
  59. int count = 0;
  60. int count1 = 0;//计算加入状态顶点0时,包含的边数目,若包含状态顶点0,则只是包含两条边
  61. for(int i = 0;i < list.size();i++) {
  62. edge p = list.get(i);
  63. int a = p.a;
  64. int b = p.b;
  65. if(find(a) != find(b) && count < n - 1) {
  66. temp += p.value;
  67. union(a, b);
  68. count++;
  69. if(a == 0 || b == 0)
  70. count1++;
  71. } else if(p.value < 0) //此时,修这条路是一定赚钱的,所以必修
  72. temp += p.value;
  73. else if(count == n - 1 && p.value > 0)
  74. break;
  75. }
  76. if(count == n - 1 && (count1 == 0 || count1 > 1))
  77. result = Math.min(result, temp);
  78. }
  79. public static void main(String[] args) {
  80. Main test = new Main();
  81. Scanner in = new Scanner(System.in);
  82. n = in.nextInt();
  83. m = in.nextInt();
  84. id = new int[n + 1];
  85. for(int i = 0;i <= n;i++)
  86. id[i] = -1;
  87. for(int i = 0;i < m;i++) {
  88. int a = in.nextInt();
  89. int b = in.nextInt();
  90. int c = in.nextInt();
  91. list.add(new edge(a, b, c));
  92. }
  93. test.kruskal(); //此处用于寻找不含码头的最后生成树得出的结果
  94. for(int i = 0;i <=n;i++)
  95. id[i] = -1;
  96. int[] point = new int[n]; //使用码头连通
  97. for(int i = 0;i < n;i++)
  98. point[i] = in.nextInt();
  99. for(int i = 0;i < n;i++) {
  100. if(point[i] == -1)
  101. continue;
  102. list.add(new edge(0, i + 1, point[i])); //添加一个顶点0状态地点,所有码头均可到
  103. }
  104. n = n + 1; //此处是因为增加了一个状态顶点0,所以n要加1
  105. test.kruskal(); //此处用于寻找包含码头的最小生成树的出的结果
  106. System.out.println(result);
  107. }
  108. }

Java实现 蓝桥杯 历届试题 城市建设的更多相关文章

  1. Java实现蓝桥杯历届试题分考场

    历届试题 分考场 时间限制:1.0s 内存限制:256.0MB 提交此题 问题描述 n个人参加某项特殊考试. 为了公平,要求任何两个认识的人不能分在同一个考场. 求是少需要分几个考场才能满足条件. 输 ...

  2. Java实现蓝桥杯历届试题兰顿蚂蚁

    历届试题 兰顿蚂蚁 时间限制:1.0s 内存限制:256.0MB 提交此题 问题描述 兰顿蚂蚁,是于1986年,由克里斯·兰顿提出来的,属于细胞自动机的一种. 平面上的正方形格子被填上黑色或白色.在其 ...

  3. Java实现蓝桥杯历届试题回文数字

    历届试题 回文数字 时间限制:1.0s 内存限制:256.0MB 提交此题 问题描述 观察数字:12321,123321 都有一个共同的特征,无论从左到右读还是从右向左读,都是相同的.这样的数字叫做: ...

  4. Java实现蓝桥杯历届试题高僧斗法

    历届试题 高僧斗法 时间限制:1.0s 内存限制:256.0MB 提交此题 锦囊1 锦囊2 问题描述 古时丧葬活动中经常请高僧做法事.仪式结束后,有时会有"高僧斗法"的趣味节目,以 ...

  5. Java实现蓝桥杯历届试题买不到的数目

    历届试题 买不到的数目 时间限制:1.0s 内存限制:256.0MB 提交此题 锦囊1 锦囊2 问题描述 小明开了一家糖果店.他别出心裁:把水果糖包成4颗一包和7颗一包的两种.糖果不能拆包卖. 小朋友 ...

  6. Java实现 蓝桥杯 历届试题 斐波那契

    试题 历届试题 斐波那契 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 斐波那契数列大家都非常熟悉.它的定义是: f(x) = 1 - (x=1,2) f(x) = f(x-1) ...

  7. Java实现 蓝桥杯 历届试题 小计算器

    历届试题 小计算器 时间限制:1.0s 内存限制:256.0MB 问题描述 模拟程序型计算器,依次输入指令,可能包含的指令有 1. 数字:'NUM X',X为一个只包含大写字母和数字的字符串,表示一个 ...

  8. Java实现蓝桥杯 历届试题 k倍区间

    历届试题 k倍区间 时间限制:2.0s 内存限制:256.0MB 问题描述 给定一个长度为N的数列,A1, A2, - AN,如果其中一段连续的子序列Ai, Ai+1, - Aj(i <= j) ...

  9. Java实现 蓝桥杯 历届试题 小数第n位

    历届试题 小数第n位 时间限制:1.0s 内存限制:256.0MB 问题描述 我们知道,整数做除法时,有时得到有限小数,有时得到无限循环小数. 如果我们把有限小数的末尾加上无限多个0,它们就有了统一的 ...

随机推荐

  1. 在一段字符串中的指定位置插入html标签,实现内容修改留痕

    客户需求:实现内容修改留痕,并且鼠标移动到元素时,显示修改人和修改时间. (其实呢本人觉得这个如果是静态的页面,或者是后端拼接好的html,都很好实现,如果让前端动态实现就......) 前端实现的方 ...

  2. 如何用尾插法建立双链表(C语言,非循环)

    如何用尾插法建立双链表 其实本来是想完成汪队给的链表快排的作业,但是我写完建立双链表以后就12点了龟龟,明天还要早起QAQ,我菜死了 一,为啥要有双链表 先说单链表吧单链表长这样 他的一个结点结构就是 ...

  3. vue的slot

    1.明确一点:分发内容是在父作用域内编译: 2.slot作为备用内容的条件:宿主元素为空且父元素没有要分发的内容. 3.具名slot:<slot name="XXX"> ...

  4. SpringBoot整合Redis实现简单的set、get

    一.导入pom.xml文件相关的依赖并配置 <dependency> <groupId>org.springframework.boot</groupId> < ...

  5. k8s搭建实操记录干货二(node)

    #注:172.16.110.111为master,172.16.110.112\114为node1\node2(kubeadm join部分要等master完成后手工操作,其它可执行本脚本一键安装) ...

  6. POJ1905

    题目链接:http://poj.org/problem?id=1905 题目大意: 竹竿受热会膨胀.设其原长为 L ,受热膨胀后的长度 L'=(1+n*C)*L ,其中 n, C, L都是要输入的参数 ...

  7. tomcat启动失败怎么回事?

    1.系统环境没有配置好 2.web.xml文件里有错误拼写

  8. uniapp打包发版到linux服务器步骤----H5端

    最近在写uni-app项目,项目打包部署到服务器后,搞了好一会一直打开是空白页,原来自己有几个地方疏忽了,现把步骤整理一下: 第1步:编辑配置 mainifest.json 文件 tip:运行的基础路 ...

  9. Java基础以及变量和运算符、包机制、javadoc生成

    目录 注释.标识符.关键字 注释 标识符 关键字 标识符注意点 数据类型 强类型语言 弱类型语言 Java的数据类型 基本类型(primitive type) 数值类型 boolean类型 什么是字节 ...

  10. PHP文件目录操作

    目录操作 is_dir ( $path ) 判断当前路径是否为目录 ,返回布尔 opendir ( $path ) 打开路径目录,返回资源 readdir ( $handle ) 读取当前打开目录下一 ...