1. 程式人生 > >PREV-9-藍橋杯-歷屆試題-大臣的旅費

PREV-9-藍橋杯-歷屆試題-大臣的旅費

元素 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-藍橋杯-歷屆試題-大臣的旅費