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;
}
posted @ 2019-10-16 19:58  prestige  阅读(81)  评论(0编辑  收藏  举报