参考资料:
dijkstra和Floyd算法思想:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html
C++代码版:http://blog.csdn.net/moilk_nepho/article/details/52950546
JAVA优先队列使用:http://www.importnew.com/6932.html
JAVA类中类问题:https://www.baidu.com/s?ie=UTF-8&wd=java%20%E7%B1%BB%E4%B8%AD%E7%B1%BB
Comparable 和Comparator 详解及区别:http://blog.csdn.net/sinat_34979528/article/details/54407678
cannot be cast to java.lang.Comparable解决办法:http://blog.sina.com.cn/s/blog_944bf8ef0101jczp.html
解题思路:
题目要求 “所有城市到首都的最短距离都和原来一样长” 可见这是一个单源最短路径问题。
且要求出最少要改造多少铁路,即要求:所有符合最短路径条件的边,用这样的边,连通所有点所需要的最小花费。
样例:
package csp2016_09_4;
/**
* 收获:
* 到底是对象运算快还是普通运算快 在这里——用静态还是动态好?
* djs算法和延伸
* 常见图论算法的写法
* 类中类的问题
* final static
* List的使用及List[]时要注意每项都实例化
* 优先队列PriorityQueue
* Comparator和Comparable区别和使用细节
*
* */
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;
class Node implements Comparable<Node>{
//出发点到V点的距离为cost
public int v=0,cost=0;
Node(){}
Node(int v,int cost){
this.v = v;
this.cost = cost;
}
public int compare(Node o1, Node o2) {
// return ((Node)o1).cost-((Node)o2).cost; //Comparator<默认Object>
return o1.cost-o2.cost;
}
@Override
public int compareTo(Node o) {
return this.cost-o.cost;
}
// public static Comparator<Node> costComparator = new Comparator<Node>(){
// public int compare(Node c1, Node c2) {
// return (c1.cost - c2.cost);
// }
// };
}
class Edge{
// 该点到点V的距离为W
int v,w=0;
Edge(int v,int w){
this.v = v;
this.w = w;
}
// int s=0,e=0,w=0;
// Edge(int s,int e,int w){
// this.s = s;
// this.e = e;
// this.w = w;
// }
}
public class Main {
Main(){
for (int i = 0; i < G.length; i++) {
G[i] = new ArrayList();
}
}
final static int MAXN = 10010;
final static int MAXINT = 0xfffffff;
// ArrayList G[] = new ArrayList[MAXN];
List <Edge>G[] = new ArrayList[MAXN];
boolean vis[] = new boolean[MAXN]; //每个点只应该被访问一次
int dis[] =new int[MAXN]; //出发点到某点的距离
// int prev[] = new int[MAXN]; //传统djs,求前驱顶点,得最短路径
int costo[] = new int[MAXN]; //当满足最短路径条件下,要接通该点所需要的最小花费。
int n,m;
public static void main(String[] args) {
Main a = new Main();
Scanner sc = new Scanner(System.in);
a.n = sc.nextInt();
a.m = sc.nextInt();
// int[][] A = new int[m][3];
// for (int i = 0; i < A.length; i++) {
// for (int j = 0; j < A[i].length; j++) {
// A[i][j] = sc.nextInt();
// }
// }
// Main.run();
int s,e,w;
for (int i = 0; i < a.m; i++) {
s = sc.nextInt();
e = sc.nextInt();
w = sc.nextInt();
// Edge edge = a.new Edge(e,w);
a.G[s].add(new Edge(e,w));
a.G[e].add(new Edge(s,w)); //双向连通
}
a.djs(1);
int ans = 0;
for (int i = 2; i <= a.n; i++) { //没有结点0,本题1到1的距离还是0
ans += a.costo[i];
}
System.out.println(ans);
}
public void djs(int s){
//初始化
for (int i = 0; i <= n; i++) {
dis[i] = MAXINT;
costo[i] = MAXINT;
vis[i] = false;
}
//自己到自己肯定是0
dis[s] = 0;
costo[s] = 0;
// 是0不是s 本题不存在结点0 初始开始结点需要是1
vis[0] = true;
//建立优先队列pq 存储Node结点信息
// Node comp = new Node(); //如果调用的是Comparator接口就这样写
// Queue<Node> pq = new PriorityQueue<Node>(comp);
Queue<Node> pq = new PriorityQueue<Node>();
//初始化
pq.add(new Node(s,0));
Node temp;
while(!pq.isEmpty()){
temp = pq.poll(); //从最近的开始取 取完删除
int v = temp.v;
if(!vis[v]){
vis[v] = true;
//看看你这个点v周围连了几个边
int length = G[v].size();
//对每个边循环一次
for (int i = 0; i < length; i++) {
//目标点:vv
int vv = G[v].get(i).v;
if(vis[vv]) continue;
//从点v到点vv 边长为cost
int cost = G[v].get(i).w;
//假如从v沿这条边到vv 那么就得到了新的权值
int newdis = dis[v] + cost;
//eg:A->B=6 A->C=3 C->B=2 已经到C了 发现6>3+2=5
if(dis[vv] > newdis){
//那起始点A --->B 的距离就改成5了
dis[vv] = newdis;
//目前要连通点B且满足最短路径条件 所需的最小花费就是2了
costo[vv] = cost; //v到VV的花费
//下一个,把点B放入pq中
pq.add(new Node(vv,dis[vv]));
}
//eg:A->B=5? 多种距离相同的方案,选取新边最小那个
if(dis[vv] == newdis){
costo[vv] = Math.min(costo[vv],cost);
}
}
}
}
}
}