很久以前,T王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。
为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。
J是T国重要大臣,他巡查于各大城市之间,体察民情。所以,从一个城市马不停蹄地到另一个城市成了J最常做的事情。他有一个钱袋,用于存放往来城市间的路费。
聪明的J发现,如果不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,在走第xx千米到第x+1x+1千米这一千米中(xx是整数),他花费的路费是x+10x+10这么多。也就是说走11千米花费1111,走22千米要花费2323。
J大臣想知道:他从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?
O problema por um longo tempo para escrever este frango fraco, que é o primeiro contato com o diâmetro do conceito de árvore de
árvores de diâmetro é a árvore mais distante distância entre quaisquer dois pontos (também referida como a cadeia mais longa)
dois diâmetros da árvore Método de solução (1) Árvore dp (2) Duas vezes dfs (bfs)
Aqui precisamos conhecer as duas propriedades da árvore
(1) A partir de qualquer ponto, a soma da cadeia mais longa e a segunda cadeia mais longa nesse momento é essa árvore O diâmetro
específico pode ser referido
aqui
(2) Começando em qualquer ponto e procurando um ponto na distância mais distante, esse ponto é definitivamente um ponto final do diâmetro da árvore.Por
que o primeiro ponto encontrado deve ser o ponto final
com este 2? Você pode fazer esta pergunta com um ponto de conhecimento:
Primeiro, apresentarei o código do bfs (o dfs é fácil de estourar a pilha no JAVA; portanto, se você estiver usando o JAVA, é melhor usar o 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();
}
}
Abaixo está o código do 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();
}
}
Você pode ver que alguém aqui é um pouco ignorante.Se a lista de adjacências é implementada com uma matriz? ? ? Não entendi a estranheza de assistir. Como esse frango fraco é o caso
, deixe-me apresentar a realização da
matriz da lista de adjacências.Nota: O número da borda da lista de adjacências é muito importante
(1) Usamos matrizes u, v, w 3 para armazenar as 3 informações da borda ( Ponto inicial, ponto final, peso)
(2) Usamos a matriz p para armazenar o número da primeira aresta de cada vértice e a próxima matriz para armazenar se alguns vértices tiverem mais de uma aresta, a próxima matriz desempenhará um papel
Vamos descrevê-lo em detalhes abaixo: Por
exemplo, temos 5 pontos
1 2 3 4 5
Temos 4 arestas numeradas
1 2 3 4
1: 2-3 8
2: 3-4 5
3: 2-1 3 Por
enquanto, apenas 3 arestas ele preguiça não quer escrever
lidos para os primeiros lados:
[. 1] U 2 = [1.] W = 3 [1.] 8 = P [2] = 1... que deve ser claro dentro das informaes colaterais de matriz subscrito É o número da aresta, portanto, devemos distinguir claramente sobre essa coisa. Toda vez que a procuramos, procuramos de acordo com o número da aresta. A matriz p é descobrir qual aresta corresponde a esse ponto. Ao
ler a segunda aresta:
u [2] = 3 v [2] = 4 w [2] = 5 p [3] = 2 Ao
ler a terceira aresta:
u [3] = 2 v [3] = 1 w [3] = 3 p [2] = 3 (observe aqui que, se lermos assim Se entrarmos, perderemos as informações da primeira aresta do segundo ponto, então aqui apresentaremos a próxima matriz)
Nós portanto ler em
u [3] = 2, v
[3] = 1, w [3] = 3, próxima [3] = p [2] (próximo [3] = 1), p [2] = 3 nós antes deste ponto corresponde a uma borda presente na próxima matriz
quando se encontrar vamos encontrar este
p [2]: encontrado primeiro lado e próximo [p [2]] o segundo lado encontra-lo
se O frango fraco ainda não está explicado claramente, você pode consultar o link abaixo
aqui