问题描述
时间限制: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个点):
思路
题目表面是求路费,但是路费就是一个等差数列。路径越长路费越多,因此就是要先求出距离最长的两点。
在摘要也提到了一点思路:
首先用邻接矩阵存储图,降低空间复杂度以及降低时间复杂度。
核心思路:
解决这道题重点在于两次使用dijkstra算法,你需要知道“假设点离点a距离最远的点为点b,离点b最远的点是c,那么整个图最远两点肯定时b-c。 PS:(c可以等于a也可以不是a)”
我们可以通过第一次dijkstra算法找到离一个点(我取1)最远的点b,然后再通过一次dijkstra算法找到离b最远的点c。这样我们就得到了最远距离bc。
然后等差数列求和路费=(11+10+bc)*bc/2
你也可以用这个等差数列求和
代码
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[] nextmattrix;
/*
由于我们要使用PriorityQueue优先队列,java 优先队列需要实现Comparable接口。
*/
static class dist implements Comparable {
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 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 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);
}
}