问题描述

  栋栋居住在一个繁华的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要加1
test.kruskal(); //此处用于寻找包含码头的最小生成树的出的结果
System.out.println(result);
}
}

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. 可能会导致.NET内存泄露的8种行为

    原文连接:https://michaelscodingspot.com/ways-to-cause-memory-leaks-in-dotnet/作者 Michael Shpilt.授权翻译,转载请保 ...

  2. dedecms织梦建站后怎么防止被黑,加强安全漏洞措施?

    dedecms织梦建站后怎么防止被黑,加强安全漏洞措施? 很多人反映dedecms织梦网站被黑的情况,因为织梦相对来说漏洞还是挺多的,特别是新建设的站点,有些目录.文件该删的删,权限及安全都要设置,以 ...

  3. Android 组件间通信--事件驱动

    在android中,组件间通信常用的方式: 1.使用广播机制:在主页面中监听特定的广播事件,进行业务逻辑的操作,其他页面只需要根据需求发送广播即可 例如:常用app结构中,左边通常为菜单栏,点击菜单栏 ...

  4. python实现摇骰子猜大小函数升级没把加注及三大运行商短信验证过滤

    摇骰子游戏升级 此次更改增加下注功能,启动资金1000元,每次赔率都是一倍,钱输光退出. 源码: #!/user/bin/env python #-*-coding:utf-8 -*- #Author ...

  5. docker 容器核心技术

    容器的数据卷(volume)也是占用磁盘空间,可以通过以下命令删除失效的volume: [root@localhost]# sudo docker volume rm $(docker volume ...

  6. mysqldump 参数--single-transaction

    其实很简单,single-transaction可以让mysqldump 的时候不锁表.但是他有3个前提 innodb的引擎 不能在执行的同时,有其他alter table ,drop table,r ...

  7. python3.x 基础三:文件IO

    打开文件的两种方式 1.直接打开文件并赋值给变量,打开后得到操作句柄,但不会自动关闭 file = open('文件名‘,'打开模式',’编码‘) fd = open('../config/file1 ...

  8. Jmeter基础-下载与安装

    jmeter下载与安装 下载网址:http://jmeter.apache.org/download_jmeter.cgi windows点击下载zip文件 该版本需要JDK1.8及以上版本 免安装, ...

  9. kali中安装漏洞靶场Vulhub(超详细)

    前言 我们都知道,在学习网络安全的过程中,搭建漏洞靶场有着至关重要的作用.复现各种漏洞,能更好的理解漏洞产生的原因,提高自己的学习能力.下面我在kali中演示如何详细安装漏洞靶场Vulhub. 什么是 ...

  10. HTTP 规范中的那些暗坑

    HTTP 协议可以说是开发者最熟悉的一个网络协议,「简单易懂」和「易于扩展」两个特点让它成为应用最广泛的应用层协议. 虽然有诸多的优点,但是在协议定义时因为诸多的博弈和限制,还是隐藏了不少暗坑,让人一 ...