Blue Bridge Cup Test Question J: Travel of the Minister

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

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

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

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

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

The problem for a long time to write this weak chicken, which is the first contact to the diameter of the concept of tree
diameter trees is the tree furthest distance between any two points (also referred to as the longest chain)
two diameters of the tree Solution method (1) Tree shape dp (2) Twice dfs (bfs)
Here we need to know the two properties of the tree
(1) Starting from any point, the sum of the longest chain and the second longest chain at this point is this tree the diameter of the
specific reference
here
(2) starting from any point, through a search to find the most distant point, then this point is definitely one endpoint of the diameter of the tree
point why must first find an endpoint
with these 2 You can do this question with a knowledge point.
First of all, I will introduce the code of bfs (dfs is easy to pop the stack in JAVA, so if you are using JAVA, it is best to use BFS)

package lan4A_C;
import java.io.*;
import java.util.*;
public class TestJ {
	static int MAX = 10010;
	static int n;
	static int p[]; //存每个点的一条边的编号
	static int u[]; //边的起点
	static int v[]; //边的终点
	static int w[]; //边的权值
	static int next[]; // 下一条边编号
	static int dist[]; // 到每一个的距离
	static boolean vis[]; // 点是否访问过
	static int get(int x){ // 路径转费用
		int t = 10;
		int sum = 0;
		for(int i = 1;i <= x;i++){
			sum += i+t;
		}
		return sum;
	}
	static int id = 1;
	static void add(int a,int b,int x){
		u[id] = a;
		v[id] = b;
		w[id] = x;
		next[id] = p[a];
		p[a] = id++;
	}
	static void bfs(int k){
		Queue<Integer> q = new LinkedList<Integer>();
		q.add(k);
		Arrays.fill(vis, false);
		vis[k] = true;
		dist[k] = 0;
		while(!q.isEmpty()){
			int t = q.poll();
			for(int i = p[t];i != -1;i = next[i]){ // 找到这个点的第一条边编号
				if(vis[v[i]])
					continue;
				dist[v[i]] = dist[t]+w[i]; // k点到v[i]点的距离
				q.add(v[i]);
				vis[v[i]] = true; // 这个终点已经算过了
			}
		}
	}
	public static void main(String[] args) throws IOException{
		StreamTokenizer re = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
		PrintWriter pr = new PrintWriter(new OutputStreamWriter(System.out));
		re.nextToken(); n = (int)re.nval;
		p = new int[MAX]; u = new int[MAX*2]; v = new int[MAX*2]; w = new int[MAX*2]; next = new int[MAX*2];
		vis = new boolean[MAX]; dist = new int[MAX];
		Arrays.fill(p,-1);
		Arrays.fill(next,-1);
		for(int i = 1;i < n;i++){
			re.nextToken();int a = (int)re.nval;
			re.nextToken();int b = (int)re.nval;
			re.nextToken();int x = (int)re.nval;
			add(a,b,x);
			add(b,a,x);
		}
		bfs(1);
		int k = 1;
		for(int i = 2;i <= n;i++)
			if(dist[i] > dist[k])
				k = i;  // 最远距离 第一个端点
//		System.out.println(k);
		bfs(k);
		int t = dist[1];
		for(int i = 1;i <= n;i++)
			if(dist[i] > t)
				t = dist[i];
//		System.out.println(t);
		long ans = get(t);
		pr.println(ans);
		pr.flush();
	}
}

Below is the code of DP

package lan4A_C;
import java.io.*;
import java.util.Arrays;
public class TestJDP {
	static int MAX = 10010;
	static int n;
	static int p[]; //存每个点的一条边的编号
	static int u[]; //边的起点
	static int v[]; //边的终点
	static int w[]; //边的权值
	static int next[]; // 下一条边编号
	static int d[] = new int[MAX];
	static boolean vis[] = new boolean[MAX];
	static int ans = 0;
	static int id = 0;
	static void add(int a,int b,int x){
		u[id] = a;
		v[id] = b;
		w[id] = x;
		next[id] = p[a];
		p[a] = id++;
	}
	static int get(int x){
		int t = 10;
		int sum = 0;
		for(int i = 1;i <= x;i++){
			sum += i+t;
		}
		return sum;
	}
	static void dp(int x){
		vis[x] = true;
		for(int i = p[x];i != -1;i = next[i]){
			int y = v[i];
			if(vis[y])
				continue;
			dp(y); // 先计算儿子结点的最长链
			// ans每次都为最长链加次长链的结果
			// d[x]表示从x结点出发的最长链,而如果我们之前找到的一个方向的
			//最长链,现在发现这个点从另外一个儿子结点出去,那边还有更长的最
			//长链,我们就把另外那条链当做最长链  d[x]+d[y]+w[w] 表示的是当
			//前已知的最长链加上从另外一个儿子结点出发的最长链,取最大值,这
			//个值则必然是最大值
			ans = Math.max(ans, d[x]+d[y]+w[i]);
			d[x] = Math.max(d[x], d[y]+w[i]); // d[x]每次都为最长链
		}
	}
	public static void main(String[] args) throws IOException{
		StreamTokenizer re = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
		PrintWriter pr = new PrintWriter(new OutputStreamWriter(System.out));
		re.nextToken(); n = (int)re.nval;
		p = new int[MAX]; u = new int[MAX*2]; v = new int[MAX*2]; w = new int[MAX*2]; next = new int[MAX*2];
		Arrays.fill(p, -1);
		Arrays.fill(next, -1);
		Arrays.fill(vis, false);
		for(int i = 1;i < n;i++){
			re.nextToken();int a = (int)re.nval;
			re.nextToken();int b = (int)re.nval;
			re.nextToken();int x = (int)re.nval;
			add(a,b,x);
			add(b,a,x);
		}
		dp(1);
		pr.println(get(ans));
		pr.flush();
	}
}

You may see that someone here is a bit ignorant. If the adjacency list is implemented with an array? ? ? I didn't understand the strangeness of watching. Because this weak chicken is the case
, let me introduce you to the realization of the
array of the adjacency list. Note: The number of the edge of the adjacency list is very important
(1) We use u, v, w 3 arrays to store the 3 information of the edge ( Start point, end point, weight)
(2) We use the p array to store the number of the first edge of each vertex, and the next array to store if some vertices have more than one edge, the next array will play a role
Let's describe it in detail below. For
example, we have 5 points
1 2 3 4 5
We have 4 edges numbered
1 2 3 4
1: 2-3 8
2: 3-4 5
3: 2-1 3 For the

time being, only 3 edges it too lazy not want to write
read into the first sides:
U [. 1] V 2 = [. 1] W =. 3 [. 1]. 8 = P [2] =. 1 we should be clear inside the side information array subscript It is the number of the edge, so we must distinguish clearly about this thing. Every time we search for it, we look for it according to the number of the edge. The p array is to find which edge corresponds to this point. When
reading the second edge:
u [2] = 3 v [2] = 4 w [2] = 5 p [3] = 2 When
reading the third edge:
u [3] = 2 v [3] = 1 w [3] = 3 p [2] = 3 (Please note here that if we read like this If we enter, we will lose the information of the first edge of the second point, so here we introduce the next array)
We thus read into
u [3] = 2, v
[3] = 1, w [3] = 3, next [3] = p [2] (next [3] = 1), p [2] = 3 we before this point corresponds to an edge present on the next array
when we find we will find this
p [2]: found first side and next [p [2]] the second side will find it
if The weak chicken is still not explained clearly, you can refer to the link below
here

Published 32 original articles · praised 5 · visits 862

Guess you like

Origin blog.csdn.net/shizhuba/article/details/104917250