PREV-9-藍橋杯-歷屆試題-大臣的旅費
阿新 • • 發佈:2019-03-23
元素 pre .html 藍橋杯 重復 數組 back 防止 [1]
這道題我也不會寫,然後參考了這篇---->
出自:https://www.cnblogs.com/tonghao/p/4740425.html
要用兩次DFS求最長的距離。
而最遠的點G-D,他們之間的距離即整棵樹距離最長。
這裏默認他們的權值為1,只是為了說明原理,具體搜索要根據路徑的權值來定。
先給出所有的代碼,然後對代碼各部分進行詳細解釋。
1 import java.util.ArrayList;
2 import java.util.Arrays;
3 import java.util.Scanner;
4
5 //動態鏈表
6 class Vertex{
7 ArrayList<Integer> V=new ArrayList();
8 }
9 class Edge{
10 ArrayList<Integer> E=new ArrayList();
11 }
12
13 public class Main {
14 final static int INF=0X3f3f3f3f;//10^9一般數都達不到這個,所以用它作為最大值
15 final static int maxn=100000;
16 static Vertex[] v=new Vertex[maxn+5];// V[i]存儲與i相鄰接的節點
17 static Edge[] e=new Edge[maxn+5];//e[i]存儲與i鄰接的邊的距離
18 static boolean vis[]=new boolean[maxn+5];//防止重復訪問
19 static int dis[]=new int[maxn+5];//存儲原始結點到各結點的dfs距離
20
21 static void init(int n){//初始化
22 for(int i=0;i<n;i++){
23 v[i]=new Vertex();// 為每個城市都創建一條鏈表,用來記錄它所能鄰接的城市
24 e[i]=new Edge();
25 }
26 }
27
28 static void dfs(int a){
29 int len=v[a].V.size();//與a相鄰接的城市有幾個
30 vis[a]=true;//a城市已經訪問
31 for(int i=0;i<len;i++){//遍歷城市
32 int j=v[a].V.get(i);//依次獲取a鄰接的幾個城市
33 if(!vis[j]&&e[a].E.get(i)!=INF){
34 vis[j]=true;
35 dis[j]=dis[a]+e[a].E.get(i);
36 dfs(j);
37 vis[j]=false;//回溯
38 }
39 }
40 }
41
42 public static void main(String[] args) {
43 Scanner sc=new Scanner(System.in);
44 int n=sc.nextInt();
45
46 init(n);
47
48 for(int i=0;i<n-1;i++){
49 int a=sc.nextInt()-1;
50 int b=sc.nextInt()-1;
51 int c=sc.nextInt();
52 v[a].V.add(b);//a城市可以到b,所以,在他的鏈表裏添加b
53 e[a].E.add(c);//用e記錄對應的a-b的距離
54 v[b].V.add(a);//反之b可以到a
55 e[b].E.add(c);//用e記錄對應的b-a的距離
56 }
57
58 //此類包含用來操作數組(比如排序和搜索)的各種方法
59 //將制定的false,INF分配給對應數組中的每個元素,相當於for初始操作的簡化
60 Arrays.fill(vis,false);
61 Arrays.fill(dis,INF);
62
63 dis[0]=0;
64 dfs(0);//第一次遍歷 求得某個城市到最遠的城市的最大距離是多少,並用dis[]來記錄 比如sid[1]=67;
65 long max=-1;
66 int temp=-1;
67 for(int i=0;i<n;i++){
68 if(dis[i]>max){
69 max=dis[i];
70 temp=i;
71 }
72 }
73
74 Arrays.fill(vis, false);
75 Arrays.fill(dis, INF);
76
77 dis[temp]=0;
78 dfs(temp);//第二次遍歷 求b與?距離最遠
79 long ans=-1;//防止越界
80 for(int i=0;i<n;i++){
81 if(dis[i]>ans){
82 ans=dis[i];
83 temp=i;
84 }
85 }
86 ans=ans*(ans+21)/2;
87 System.out.println(ans);
88 sc.close();
89
90 }
91
92 }
自定義兩個類,分別構造了動態鏈表。
INF=0X3f3f3f3f 可自行百度,簡潔意思就是0X3f3f3f3f即十進制的 10的9次方,表示一個超大的數,一般情況都達不到。此處用作後面作為一個標誌。
maxn 作用可能是因為在藍橋杯提交檢測時最後輸入的n是10000;所以在初始定義的時候就先創建一個比10000大的範圍,所以 後面用了 maxn+5
init(n)就是確定具體的動態鏈表多長
看main方法中:
DFS深度優先搜索:
在之前,先把數據準備好,
執行過程——> 可能有些亂。。但花了很久時間。
第一次dfs結束後,dis[ ]存儲了0到各城市的距離,在之後的操作中就是得到最遠距離max,且用temp記錄下與0最遠的城市,也就是城市4,下標為3
第二次遍歷就是從3開始了。這次要找到距離3最遠的城市。步驟原理同上,
這是第二次DFS結束,可以看出最遠的應該是dis[4] 距離為9
然後進行最後的計算就可以得出所花費的錢了。
好像代碼裏的註解會有些錯誤,因為代碼裏的註釋不是最後的理解,有錯好像沒更改過來?
PREV-9-藍橋杯-歷屆試題-大臣的旅費