P1099 树网的核
题面:https://www.luogu.org/problem/P1099
本题直接考虑直径上的点和直径外的点对选定路径的贡献即可.
Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<ctime>
using namespace std;
const int N=100005;
int n,s,head[N],dep[N],fa[N],cnt,ans=0x3f3f3f3f;
bool vis[N];
struct Node{
int u,v,w,nxt;
}edge[N*2];
void add(int u,int v,int w){
++cnt;
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].nxt=head[u];
head[u]=cnt;
}
int bfs(int s){
queue<int> q;
int depth=s;
q.push(s);
fa[s]=0;
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].v;
if(v!=fa[u]&&!dep[v]){
dep[v]=dep[u]+edge[i].w;
fa[v]=u;
q.push(v);
depth=dep[depth]<dep[v]?v:depth;
}
}
}
return depth;
}
int dfs(int u){
int s=0;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].v;
if(v!=fa[u]&&!vis[v]){
s=max(dfs(v)+edge[i].w,s);
}
}
return s;
}
int main(){
int u,v,w,root;
scanf("%d%d",&n,&s);
for(int i=1;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
root=bfs(1);
memset(dep,0,sizeof(dep));
memset(fa,0,sizeof(fa));
root=bfs(root);
for(int i=root,j=root;i;i=fa[i]){
while(dep[j]-dep[i]>s){
j=fa[j];
}
ans=min(ans,max(dep[root]-dep[j],dep[i]));
}
for(int i=root;i;i=fa[i]){
vis[i]=1;
}
for(int i=root;i;i=fa[i]){
ans=max(ans,dfs(i));
}
printf("%d\n",ans);
return 0;
}