分析:
- 构造最小生成树的时候需要用到道路的排序,所以对起始节点终止节点和道路花费进行封装,然后对边进行归并
- 然后依次归并最小花费价值的道路对应的节点
- 一条道路上当两个节点都被归并的时候不可以再次归并
/**
*@author yangyvting
*@date 2019年5月5日
*/
package 图论;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static int n , m; //城市的个数和对应的道路数目
public static boolean vis[];
public static int riverWay[];
public static Edge edgeWay[];
public static int min = 0;
public static int t = 0;
public static void main(String[] args) {
Scanner sca = new Scanner(System.in);
n = sca.nextInt();
m = sca.nextInt();
vis = new boolean[n + 1];
riverWay = new int[n + 1];
edgeWay = new Edge[n + m];
//输入道路
for(int i = 0; i < m; i ++) {
int x = sca.nextInt();
int y = sca.nextInt();
int z = sca.nextInt();
edgeWay[t ++] = new Edge(x, y, z);
}
//输入码头 //将码头算到图中
for(int i = 0; i < n; i ++) {
riverWay[i + 1] = sca.nextInt();
edgeWay[t ++] = new Edge(0, i + 1, riverWay[i + 1]);
}
//生成最小生成树
Kruscal();
//最小花费
System.out.println("最小花费为:");
System.out.println(min);
}
private static void Kruscal() {
Arrays.sort(edgeWay);
System.out.println("道路消费从小到大排序为:");
for(int i = 0; i < 2 * n; i ++) {
System.out.println(edgeWay[i].toString());
}
for(int i = 0; i < 2 * n; i ++) {
if( edgeWay[i].weight < 0) continue;
if(!vis[edgeWay[i].start] || !vis[edgeWay[i].end] ) {
min += edgeWay[i].weight;
vis[edgeWay[i].start] = vis[edgeWay[i].end] = true;
}
}
}
}
class Edge implements Comparable<Edge>{
int start;
int end;
int weight;
Edge(int start, int end, int weight ){
this.start = start;
this.end = end;
this.weight = weight;
}
@Override
public int compareTo(Edge o) {
return this.weight - o.weight;
}
public String toString() {
String st = new String();
st = this.start + " " + this.end + " " + this.weight;
return st;
}
}
运行结果
5 5
1 2 4
1 3 -1
2 3 3
2 4 5
4 5 10
-1 10 10 1 1
道路消费从小到大排序为:
1 3 -1
0 1 -1
0 4 1
0 5 1
2 3 3
1 2 4
2 4 5
4 5 10
0 2 10
0 3 10
最小花费为:
9