树的直径:2024.4.13 树的直径 - Virtual Judge
------------------------------------------------~~~~~一道板子题~~~~~------------------------------------------------
树的直径:树的直径就是树中所有最短路经距离的最大值
共两种求法:1.树形dp,我之前写过一篇—— 《树上问题——树形dp-CSDN博客》
2.二次扫描(2次bfs或dfs)
今天主要讲第2种
我们先看看这个题:
Given a tree T with non-negative weight, find the diameter of the tree.
The diameter of a tree is the maximum distance between two nodes in a tree.
Input
n
s1 t1 w1
s2 t2 w2
:
sn-1 tn-1 wn-1
The first line consists of an integer n which represents the number of nodes in the tree. Every node has a unique ID from 0 to n-1 respectively.
In the following n-1 lines, edges of the tree are given. si and ti represent end-points of the i-th edge (undirected) and wi represents the weight (distance) of the i-th edge.
Output
Print the diameter of the tree in a line.
Constraints
1 ≤ n ≤ 100,000
0 ≤ wi ≤ 1,000
Sample Input 1
4
0 1 2
1 2 1
1 3 3
Sample Output 1
5
Sample Input 2
4
0 1 1
1 2 2
2 3 4
Sample Output 2
7
其实就是很单纯的想让你求树的直径(无根树),我们下面来解剖以下代码:
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int N=1e5+100;
struct edge{
int v,w;//可用结构体,也可用make_pair
};
vector<edge>son[N];
int d[N],n,maxd,x,A,B;//maxd是最大距离
void dfs(int u,int fa){//深搜
int k=son[u].size();
for(int i=0;i<k;i++){
int v=son[u][i].v,w=son[u][i].w;
if(v==fa)continue;
d[v]=d[u]+w;//d数组记录距离,w是边权
if(d[v]>maxd)maxd=d[x=v];
dfs(v,u);
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
int u,w,v;
scanf("%d%d%d",&u,&v,&w);
u++,v++;
son[u].push_back((edge){v,w});
son[v].push_back((edge){u,w});//无根树读入
}
dfs(1,0);
d[x]=0;
dfs(x,0);//二次扫描
printf("%d\n",maxd);
return 0;
}
再来一道!
2024.4.13 树的直径 - Virtual Judge
来,大家想一想,这题能用树的直径吗?🧐🧐🧐
不但能用,还得用两次!
用两次树的直径,这题就AK了
#include<iostream>//对于代码我不敢做任何评价( ̄▽ ̄)"
#include<cstdio>
#include<vector>
using namespace std;
const int N=1e5+100;
struct edge{
int v,w;
};
vector<edge>son[N];
int d[N],n,maxd,x,tot,s;
void dfs(int u,int fa){
int k=son[u].size();
for(int i=0;i<k;i++){
int v=son[u][i].v,w=son[u][i].w;
if(v==fa)continue;
d[v]=d[u]+w;
if(d[v]>maxd)maxd=d[x=v];
dfs(v,u);
}
}
int main(){
scanf("%d%d",&n,&s);
for(int i=1;i<n;i++){
int u,w,v;
scanf("%d%d%d",&u,&v,&w);
tot+=w;
son[u].push_back((edge){v,w});
son[v].push_back((edge){u,w});
}
maxd=0;
d[1]=0;
dfs(1,0);
d[x]=0;
maxd=0;
dfs(x,0);
tot*=2;
printf("%d\n",tot-maxd);
return 0;
}
关于树的直径,我们就讲这些
拓展:[TJOI2017] 城市 - 洛谷(我朋友竟然用线段树AK了,真·神犇大家加油!)