蓝桥杯第四届真题 :大臣的旅费

点击查看:蓝桥杯历年真题 题解目录
大臣的旅费

蓝桥杯第四届真题 :大臣的旅费_第1张图片
蓝桥杯第四届真题 :大臣的旅费_第2张图片

说明
1. 由题意知: 是一个无回路的图,也可看成树。
2. 解法一: 将其看做树
3. 遍历每个点到其他个点的距离(深度优先遍历),找出最大值,进行计算
4. 假如有四个点ABCD 即: A->B , A->C , A -> D , B->C , B->D , C-> D ,比较出最大值
5. 这种方法不是最优解,不能通过全部测试样例,部分会超时。

6. 解法二: 将其看做图(存储数据利用图,解题利用树的特点)
7. 使用邻接表存储图结构,定义 List<Node>[] 作为邻接表
8. List链表不仅要初始化,List类型的数组也要进行初始化,即 ArrayList,通过循环实现
9. List数组的链表元素的结点类型为Node,Node封装了城市编号 和 当前城市(数组索引)到达该城市的的距离
10.一共利用了两次 dfs , 第一次: 找出树的直径。即:找出首都结点到其他叶子节点中 最长路径的那个叶子节点pnt。
11. 再通过pnt为初始结点,进行一次dfs,即可找出整棵树中两节点间的 最长路径。
12. 根据得出的最长路径max 进行计算即可得出路费。
package java_2013_A;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
/**
 * @author Ren
 */
public class Main010_大臣的旅费 {
    private int n;
    private static List<Node>[] g; //图的邻接表
    private static long max = -1 ;
    private static int pnt = -1 ;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        g = new List[n+1];
        // 初始化数组
        for (int i = 1; i <= n; i++) {
            g[i]=new ArrayList<Node>();
        }
        // 读取和存储数据
        for (int i = 0; i < n - 1; i++) {
            int a = in.nextInt();
            int b = in.nextInt();
            long c = in.nextLong();
            g[a].add(new Node(b,c));
            g[b].add(new Node(a,c));
        }
        // 以1为根找出一个1到其他结点中最长路径的那个叶子节点
        dfs(1,1,0);
        dfs(pnt,pnt,0);
        System.out.println(dis2Money(max));
    }
    /**
     * @param from 上一个节点的编号
     * @param num  当前节点的编号
     * @param dis  历史上(从初始结点)积累的距离
     */
    private static void dfs(int from,int num,long dis) {
        boolean isLeaf = true;
        List<Node> neighbors = g[num];
        // 遍历链表 if语句防止往回搜索
        // 如果出了上一个结点还有其他结点说明不是叶子节点,isLeaf = false;
        for (int i = 0; i < neighbors.size(); i++) {
            Node neighbor = neighbors.get(i);
            if(neighbor.num == from) continue;
            isLeaf = false;
            dfs(num,neighbor.num,dis+neighbor.dis);
        }
        if(isLeaf && dis > max){ //是叶子节点
            max = dis;
            pnt = num;
        }
    }
    // 根据距离计算路费
    static long dis2Money(long dis){
        return (dis*dis+21*dis)/2;
    }
    static class Node{
        int num;
        long dis;
        public Node(int num, long dis) {
            this.num = num; // 城市编号
            this.dis = dis; // 到达该城市的距离
        }
    }
}

蓝桥杯第四届真题 :大臣的旅费_第3张图片

你可能感兴趣的:(#,蓝桥杯历届真题)