树的直径+证明
作者:互联网
概念
树的直径:2点距离最远的路径。
结论
先说结论,对于一颗无根树,首先随便找一个点 u 开始进行搜索,找到离当前点最远的一点 s , 然后从 s 开始搜最远的点 t ,树的直径就为 s - t 。
证明
找到直径,我们只需找到直径2个端点其中的一个,然后找到离当前点最远的点即为另一个端点。
1.首先u在s-t的路径上,很明显是对的,到达u最远的点必为s或t,因为是从u开始搜最远的点的。
2.u不在s-t的路径上,那么从u搜最远的点必然与s-t相交。
如图,如果u搜到最远的点为T,那么dis(u,t) > dis(u,x) + dis(x,t)
很显然: dis(s,t ) = dis(s,x) + dis(x,t) < dis(s,T) = dis(s,x) + dis(u,x) + dis(u,T)
所以 很容易得出必与直径相交,且搜到的点为另一个端点。
模板
void dfs(int u,int f){
for(int i = 0;i < sp[u].size();i++){
int v = sp[u][i].v;
int w = sp[u][i].w;
if(v==f)continue;
dis[v] = dis[u] + w;
dfs(v,u);
}
}
模板题
#pragma GCC optimize(2)
#include<iostream>
#include<vector>
using namespace std;
const int man = 2e5+10;
struct node{
int v,w;
node(){}
node(int v,int w){
this->v = v;
this->w = w;
}
};
vector<node>sp[man];
ll dis[man];
void dfs(int u,int f){
for(int i = 0;i < sp[u].size();i++){
int v = sp[u][i].v;
int w = sp[u][i].w;
if(v==f)continue;
dis[v] = dis[u] + w;
dfs(v,u);
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
int n,m;
cin >> n >> m;
for(int i = 1;i <= m;i++){
int u,v,w;
char c;
cin >>u >> v >>w >> c;
sp[u].push_back(node(v,w));
sp[v].push_back(node(u,w));
}
dis[1] = 0;
dfs(1,0);
ll max_ans = 0,max_i = 1;
for(int i = 1;i <= n;i++){
if(dis[i]>max_ans){
max_ans = dis[i];
max_i = i;
}
}
dis[max_i] = 0;
max_ans = 0;
dfs(max_i,0);
for(int i = 1;i <= n;i++){
max_ans = max(max_ans,dis[i]);
}
cout << max_ans <<endl;
return 0;
}
nofuck~
发布了27 篇原创文章 · 获赞 7 · 访问量 2684
私信
关注
标签:int,max,sp,dfs,证明,直径,最远,dis 来源: https://blog.csdn.net/weixin_43571920/article/details/104076421