历届试题 大臣的旅费

问题描述 

时间限制:1.0s   内存限制:256.0MB

很久以前,T王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。

为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。

J是T国重要大臣,他巡查于各大城市之间,体察民情。所以,从一个城市马不停蹄地到另一个城市成了J最常做的事情。他有一个钱袋,用于存放往来城市间的路费。

聪明的J发现,如果不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,在走第x千米到第x+1千米这一千米中(x是整数),他花费的路费是x+10这么多。也就是说走1千米花费11,走2千米要花费23。

J大臣想知道:他从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?

输入格式

输入的第一行包含一个整数n,表示包括首都在内的T王国的城市数

城市从1开始依次编号,1号城市为首都。

接下来n-1行,描述T国的高速路(T国的高速路一定是n-1条)

每行三个整数Pi, Qi, Di,表示城市Pi和城市Qi之间有一条高速路,长度为Di千米。

输出格式

输出一个整数,表示大臣J最多花费的路费是多少。

样例输入1

5
1 2 2
1 3 1
2 4 5
2 5 4

样例输出1

135

输出格式

大臣J从城市4到城市5要花费135的路费。

这是我的测评结果(网上有些代码只有75分是因为最后一个测试数据量太大10000个点):

170259_M0Zj_2851839.png

思路

题目表面是求路费,但是路费就是一个等差数列。路径越长路费越多,因此就是要先求出距离最长的两点。

在摘要也提到了一点思路:

首先用邻接矩阵存储图,降低空间复杂度以及降低时间复杂度。

核心思路:

解决这道题重点在于两次使用dijkstra算法,你需要知道“假设点离点a距离最远的点为点b,离点b最远的点是c,那么整个图最远两点肯定时b-c。  PS:(c可以等于a也可以不是a)”

我们可以通过第一次dijkstra算法找到离一个点(我取1)最远的点b,然后再通过一次dijkstra算法找到离b最远的点c。这样我们就得到了最远距离bc。

然后等差数列求和路费=(11+10+bc)*bc/2

你也可以用这个等差数列求和

  • formula

 

代码 


import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Scanner;

public class Dijkstra {
	static int nodenum = 0;
	static List<dist>[] nextmattrix;

	/*
       由于我们要使用PriorityQueue优先队列,java 优先队列需要实现Comparable接口。
     */
	static class dist implements Comparable<dist> {
		int index;
		int value;

		public dist(int i, int v) {
			this.index = i;
			this.value = v;
		}

		//优先队列比较函数,越大越靠前。o是待加入的元素,和已加入的this比较
        // 如果this>o,那么o就要排在this后面所以返回-1反之返回1
		@Override
		public int compareTo(dist o) {
			if (o.value == this.value)
				return 0;
			return (this.value > o.value) ? -1 : 1;// 大的优先
		}
	}

	//优先队列版的dijkstra算法(注意是求最大距离和其他的dijkstra有点区别)
	public static int[] dijkst(int origin) {
		PriorityQueue<dist> prioqueue = new PriorityQueue<>();
		int[] dis = new int[nodenum + 1];
		dis[origin] = 0;
		prioqueue.add(new dist(origin, 0));
		boolean[] select = new boolean[nodenum + 1];
		while (!prioqueue.isEmpty()) {
			dist temp = prioqueue.poll();
			select[temp.index] = true;
			Iterator<dist> tempnext = nextmattrix[temp.index].iterator();
			dist nextvalue;
			int sum;
			while (tempnext.hasNext()) {
				nextvalue = tempnext.next();
				int i = nextvalue.index;
				if (select[i])
					continue;
				sum = dis[temp.index] + nextvalue.value;
				if ((dis[i] < sum)) {
					dis[i] = sum;
					prioqueue.add(new dist(i, dis[i]));
				}
			}
		}
		return dis;
	}

	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		nodenum = input.nextInt();
		nextmattrix = new List[nodenum + 1];
		//构造邻接矩阵
		for (int i = 1; i < nodenum; i++) {
			int first = input.nextInt();
			int second = input.nextInt();
			int value = input.nextInt();
			if (nextmattrix[first] == null)
				nextmattrix[first] = new LinkedList<>();
			nextmattrix[first].add(new dist(second, value));
			if (nextmattrix[second] == null)
				nextmattrix[second] = new LinkedList<>();
			nextmattrix[second].add(new dist(first, value));
		}
		input.close();
		//找到离1最远的点maxpoint
		int[] dis = dijkst(1);
		int maxpoint = 0;
		int max = 0;
		for (int i = 1; i <= nodenum; i++)
			if (dis[i] > max) {
				max = dis[i];
				maxpoint = i;
			}
		//找离maxpoint距离最远距离
		dis = dijkst(maxpoint);
		for (int i = 1; i <= nodenum; i++)
			if (dis[i] > max) {
				max = dis[i];
			}
		//等差数列求和算路费
		System.out.println((11 + 10 + max) * max / 2);
	}
}

 

转载于:https://my.oschina.net/yuanmuou/blog/895092

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值