问题描述
  栋栋居住在一个繁华的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的边最少要有两条。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;public class Main {public static int n, m;public static int[] id;public static ArrayList<edge> list = new ArrayList<edge>();public static int result = Integer.MAX_VALUE;static class edge {public int a;public int b;public int value;public edge(int a, int b, int value) {this.a = a;this.b = b;this.value = value;}}class MyComparator implements Comparator<edge> {public int compare(edge o1, edge o2) {if(o1.value > o2.value)return 1;else if(o1.value < o2.value)return -1;return 0;}}public int find(int a) {int root = a;while(id[root] >= 0) {root = id[root];}int i = 0, k = a;while(k != root) {i = id[k];id[k] = root;k = i;}return root;}public void union(int a, int b) {int rootA = find(a);int rootB = find(b);if(rootA == rootB)return;int num = id[rootA] + id[rootB];if(id[rootA] < id[rootB]) {id[rootB] = rootA;id[rootA] = num;} else {id[rootA] = rootB;id[rootB] = num;}}public void kruskal() {Collections.sort(list, new MyComparator());int temp = 0;int count = 0;int count1 = 0;//计算加入状态顶点0时,包含的边数目,若包含状态顶点0,则只是包含两条边for(int i = 0;i < list.size();i++) {        edge p = list.get(i);int a = p.a;int b = p.b;if(find(a) != find(b) && count < n - 1) {temp += p.value;union(a, b);count++;if(a == 0 || b == 0)count1++;} else if(p.value < 0)  //此时,修这条路是一定赚钱的,所以必修temp += p.value;else if(count == n - 1 && p.value > 0)break;}if(count == n - 1 && (count1 == 0 || count1 > 1))  result = Math.min(result, temp);    }public static void main(String[] args) {Main test = new Main();Scanner in = new Scanner(System.in);n = in.nextInt();m = in.nextInt();id = new int[n + 1];for(int i = 0;i <= n;i++)id[i] = -1;for(int i = 0;i < m;i++) {int a = in.nextInt();int b = in.nextInt();int c = in.nextInt();list.add(new edge(a, b, c));}test.kruskal();  //此处用于寻找不含码头的最后生成树得出的结果for(int i = 0;i <=n;i++)id[i] = -1;int[] point = new int[n];  //使用码头连通for(int i = 0;i < n;i++)point[i] = in.nextInt();for(int i = 0;i < n;i++) {if(point[i] == -1)continue;list.add(new edge(0, i + 1, point[i]));  //添加一个顶点0状态地点,所有码头均可到}n = n + 1;   //此处是因为增加了一个状态顶点0,所以n要加1test.kruskal();   //此处用于寻找包含码头的最小生成树的出的结果System.out.println(result);}
}

Java实现 蓝桥杯 历届试题 城市建设相关推荐

  1. 问题 1437: [蓝桥杯][历届试题]城市建设(最小生成树)

    题目描述 栋栋居住在一个繁华的C市中,然而,这个城市的道路大都年久失修.市长准备重新修一些路以方便市民,于是找到了栋栋,希望栋栋能帮助他. C市中有n个比较重要的地点,市长希望这些地点重点被考虑.现在 ...

  2. 【Java】蓝桥杯历届试题 题解

    历届试题 PREV-1 核桃的数量 历届试题 PREV-2 打印十字图 历届试题 PREV-3 带分数 历届试题 PREV-4 剪格子 历届试题 PREV-5 错误票据 历届试题 PREV-6 翻硬币 ...

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

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

  4. Java实现 蓝桥杯 历届试题 核桃的数量

    历届试题 核桃的数量 时间限制:1.0s 内存限制:256.0MB 问题描述 小张是软件项目经理,他带领3个开发组.工期紧,今天都在加班呢.为鼓舞士气,小张打算给每个组发一袋核桃(据传言能补脑).他的 ...

  5. Java实现 蓝桥杯 历届试题 带分数

    问题描述 100 可以表示为带分数的形式:100 = 3 + 69258 / 714. 还可以表示为:100 = 82 + 3546 / 197. 注意特征:带分数中,数字1~9分别出现且只出现一次( ...

  6. Java实现 蓝桥杯 历届试题 波动数列

    问题描述 观察这个数列: 1 3 0 2 -1 1 -2 - 这个数列中后一项总是比前一项增加2或者减少3. 栋栋对这种数列很好奇,他想知道长度为 n 和为 s 而且后一项总是比前一项增加a或者减少b ...

  7. Java实现 蓝桥杯 历届试题 矩阵翻硬币

    问题描述 小明先把硬币摆成了一个 n 行 m 列的矩阵. 随后,小明对每一个硬币分别进行一次 Q 操作. 对第x行第y列的硬币进行 Q 操作的定义:将所有第 ix 行,第 jy 列的硬币进行翻转. 其 ...

  8. Java实现蓝桥杯历届试题填字母游戏

    题目描述 小明经常玩 LOL 游戏上瘾,一次他想挑战K大师,不料K大师说: "我们先来玩个空格填字母的游戏,要是你不能赢我,就再别玩LOL了".K大师在纸上画了一行n个格子,要小明 ...

  9. Java实现 蓝桥杯 历届试题 数字游戏

    问题描述 栋栋正在和同学们玩一个数字游戏. 游戏的规则是这样的:栋栋和同学们一共n个人围坐在一圈.栋栋首先说出数字1.接下来,坐在栋栋左手边的同学要说下一个数字2.再下面的一个同学要从上一个同学说的数 ...

最新文章

  1. opencv固定窗口在桌面的位置
  2. html中看到php代码_如何在HTML中嵌入PHP代码
  3. ASP.NET froms 身份验证之Roles
  4. python 虚拟环境 django.db 报错_jumpserver一体化安装
  5. Nginx 过滤模块
  6. java 放行文件_springmvc中关于静态资源的放行
  7. hudson添加批处理编译命令的注意事项
  8. 28留数及其应用(四)
  9. python错误:ImportError: DLL load failed: 找不到指定的程序,from PyQt6 import QtCore, QtGui, QtWidgets
  10. 2014计算机科学与技术学科国际学术会议ei检索目录,2014年Ei核心期刊源目录(Ei Compendex)...
  11. 联通企业专线_上海联通数据专线-企业宽带网
  12. 做一行就要把一行的本质研究透
  13. 【76.57%】【codeforces 721A】One-dimensional Japanese Crossword
  14. 曝猛! 许多行情软件自带的SAR指标是错的
  15. 计算机输入设备和输出设备怎么区分,输入设备和输出设备的区别
  16. [每日一氵] openCV resize函数直接按比例缩放
  17. UE4 VR项目设置总结
  18. 鼠标滚轮事件onmouewheel
  19. 脱裤子放屁之用两个栈实现队列、用两个队列实现栈
  20. 找出耗电大户进行消灭 电池持久有绝招——下载加速吧

热门文章

  1. 同济大学Python程序设计基础 实验九:数据可视化
  2. VS2017常用快快捷键
  3. 淘宝与日本雅虎网购平台上线;Novell公司推出SUSE Meego系统(每日关注20100602)...
  4. 推荐的几个比较好的网站和博客
  5. [篇五章四]-关于 Windows 10 没有桌面图标如何调出来
  6. 拒绝时间与脑力浪费,不做数学守旧派
  7. Tomcat 启动时间过长 Connection has been abandoned PooledConnection
  8. python公里转英里_python公里转英里_从英里换算为公里
  9. mysql back blog_mysql qpress压缩备份恢复
  10. 简报 | 印度政府最终确定加密货币监管框架