树的直径
DP做法(一次DFS):
- 首先dfs每一个点
- 对每个点求一个最大值和次大值
- 每个点将最大值+次大值与ans比较得到解
代码:
const int N = 1e5+5;
const int M = 2e6+5;
typedef long long intl;//类型转换
intl hd[N],nt[M],to[M],co[M],num=0,as=0;
intl dfs(intl u,intl pre){
intl d1=0,d2=0,d;
for(intl i=hd[u];i;i=nt[i]){
intl v=to[i];
if(v==pre) continue;
d=dfs(v,u)+co[i];
if(d>d1){
d2=d1;
d1=d;
}
else if(d>d2) d2=d;
}
as=max(as,d1+d2);
return d1;
}
两次dfs:
- 随机从一个点u出发返回离u距离最远得v点
- 重v点出发,返回里最远得w点
- v-w的距离就是直径
代码:
const int N = 1e5+5;
const int M = 2e6+5;
typedef long long intl;//类型转换
intl hd[N],nt[M],to[M],co[M],num=0,as=0,st,net[N];//as是直径
intl dfs(intl u,intl pre){
intl d1=0,d;
net[u]=u;
for(intl i=hd[u];i;i=nt[i]){
intl v=to[i];
if(v==pre) continue;
d=dfs(v,u)+co[i];
if(d>d1){
d1=d;
net[u]=net[v];
}
}
d1=max(d1,as);
return d1;
}
int main(){
dfs(1,-1);
dfs(net[1],-1);
}