交通规划-CCF往届题(系统判断WA)

这个题目的思路,是使用迪杰斯特拉来选择1号城市到其他城市的最短路径长度(题目最基本的要求);当然1号城市到达某城市的最短径可能不止一条,所以在最短路径长度一致的前提下,使新加入的城市到父城市的距离最小(贪婪),就可以保证最后在全部最短路选中的路径集合的总长度为要改造的铁路长度。


基础的算法是实现迪杰斯特拉,在父节点添加时使用了贪婪思想。(PS:然而系统判断是WA,截止编辑博客尚未找到解决方案,感谢各位看官给出意见)

试题编号: 201609-4
试题名称: 交通规划
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
  G国国王来中国参观后,被中国的高速铁路深深的震撼,决定为自己的国家也建设一个高速铁路系统。
  建设高速铁路投入非常大,为了节约建设成本,G国国王决定不新建铁路,而是将已有的铁路改造成高速铁路。现在,请你为G国国王提供一个方案,将现有的一部分铁路改造成高速铁路,使得任何两个城市间都可以通过高速铁路到达,而且从所有城市乘坐高速铁路到首都的最短路程和原来一样长。请你告诉G国国王在这些条件下最少要改造多长的铁路。
输入格式
  输入的第一行包含两个整数n, m,分别表示G国城市的数量和城市间铁路的数量。所有的城市由1到n编号,首都为1号。
  接下来m行,每行三个整数a, b, c,表示城市a和城市b之间有一条长度为c的双向铁路。这条铁路不会经过a和b以外的城市。
输出格式
  输出一行,表示在满足条件的情况下最少要改造的铁路长度。
样例输入
4 5
1 2 4
1 3 5
2 3 2
2 4 3
3 4 2
样例输出
11
评测用例规模与约定
  对于20%的评测用例,1 ≤ n ≤ 10,1 ≤ m ≤ 50;
  对于50%的评测用例,1 ≤ n ≤ 100,1 ≤ m ≤ 5000;
  对于80%的评测用例,1 ≤ n ≤ 1000,1 ≤ m ≤ 50000;
  对于100%的评测用例,1 ≤ n ≤ 10000,1 ≤ m ≤ 100000,1 ≤ a, b ≤ n,1 ≤ c ≤ 1000。输入保证每个城市都可以通过铁路达到首都。

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Scanner;
import java.lang.Integer;

public class Main {
	static HashSet<Integer> open=null;
	static HashSet<Integer> close=null;
	static int path[]=null;//1点到各点的路径长度
	static String pathInfo[]=null;//1点到各点的路径信息
	static HashMap<Integer,Integer> finallength=null;//1到各点路径的无重复集合
	static Node allnode[]=null;//所有新加入的节点
	static int start=1;
	static String info[]=null;

	public static void main(String[] args) {
		Scanner in=new Scanner(System.in);
		int nCity=0,nPath=0;
		info=in.nextLine().split(" ");

		nCity=Integer.parseInt(info[0]);
		nPath=Integer.parseInt(info[1]);
		open=new HashSet<Integer>(nCity);  
		close=new HashSet<Integer>(nCity);
		path=new int[nCity+1];//封装路径距离 
		pathInfo=new String[nCity+1];//封装路径信息
		allnode=new Node[nCity+1];
		finallength=new HashMap<Integer,Integer>(nCity+1);
		
		int source=0,dest=0,dist=0;
		for(int i=1;i<=nCity;i++){
			Node newNode=null;
			if(i==start){
				newNode=new Node(i,nCity,start);
				path[i]=0;
				pathInfo[i]=start+"";
			}else{	
				newNode=new Node(i,nCity,-1);
				path[i]=Integer.MAX_VALUE; 
			}
			open.add(i);
			newNode.child.put(i, 0);
			allnode[i]=newNode;
		}//先把节点划分到连个set中去

		for(int i=0;i<nPath;i++){
			info=in.nextLine().split(" ");
			source=Integer.parseInt(info[0]);
			dest=Integer.parseInt(info[1]);
			dist=Integer.parseInt(info[2]);
			allnode[source].child.put(dest, dist);
			allnode[dest].child.put(source, dist);
		}//输入整个图信息

/*
4 3
1 2 1
1 3 2
2 3 1

6 6
1 2 1
1 6 2
2 3 2
3 4 3
4 5 1
5 6 3
*/

		while(!open.isEmpty()){
			int nearest=getShortestPath(start);		
			if(nearest==-1){//即代表剩下的点不可达了 
				printPathInfo(nCity,start);
				return;  
			}

			int parent=allnode[nearest].parent;
			finallength.put(nearest,allnode[parent].child.get(nearest));
			close.add(nearest);//取距离start节点最近的子节点,放入close   
			open.remove(nearest);
			//重新进行距离计算了  
			Map<Integer,Integer> childs=allnode[nearest].child; 
			for(int e:childs.keySet()){//child新加入节点的子节点
				if(open.contains(e)){//如果子节点在open中
					int newlength=path[nearest]+childs.get(e);  

					if(path[e]>newlength){//之前设置的距离大于新计算出来的距离  
						path[e]=newlength;  
						pathInfo[e]=pathInfo[nearest]+"->"+e;
						allnode[e].parent=nearest;
					}else if(path[e]==newlength){  
						if(path[nearest]>path[allnode[e].parent]){
							path[e]=newlength;
							pathInfo[e]=pathInfo[nearest]+"->"+e;
							allnode[e].parent=nearest;
						}
					}
				}  
			}
		}

		printPathInfo(nCity,start);
	}

	public static void printPathInfo(int nCity,int start){   
		for(int i=1;i<=nCity;i++){
			if(i==start)continue;
			if(path[i]!=Integer.MAX_VALUE){
				System.out.println(i+":"+pathInfo[i]+" "+path[i]); 
			}else{
				System.out.println(i+":"+"can't reach!");
			}
		} 
		for(int i=1;i<=nCity;i++){
			if(i==start)continue;
			if(path[i]!=Integer.MAX_VALUE){
				System.out.print(i+":");
				int k=i;
				do{
					System.out.print(k+"<-"); 
					k=allnode[k].parent;
				}while(k!=start);
				System.out.println(start+" "+path[i]);
			}else{
				System.out.println(i+":"+"can't reach!");
			} 
		} 
		 
		int result=0;
		for(int i:finallength.keySet()){
			if(i!=start){
				result+=finallength.get(i);
			}
		}
		System.out.println(result);
	}  

	private static int getShortestPath(int start){  
		int res=-1;
		int minDis=Integer.MAX_VALUE;  
		for(int e:open){  
			int distance=path[e];  
			if(distance<minDis){  
				minDis=distance;  
				res=e;  
			}
		}  
		return res;  
	}  

}  

class Node {  
	int name;  
	HashMap<Integer,Integer> child=null;
	int parent=0;

	public Node(Integer name,int nCity,int start){  
		this.name=name; 
		child=new HashMap<Integer,Integer>(nCity);
		parent=start;
	}
}  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值