树网的核

给定一棵树,在树的直径上求一个路径,让树上的点到路径的距离的最大值最小

\[ans=min_{i,j}\{\ max\{ \ max_{i\le k\le j}(d_k),dis_{1,i},dis_{j,t} \} \} \]

根据直径的最长性 可以放缩且不影响结果

\[ans=min_{i,j}\{\ max\{ \ max_{1\le k\le t}(d_k),dis_{1,i},dis_{j,t} \} \} \]

\(t=\ max_{1\le k\le t}(d_k)\)

\[ans=min_{i,j}\{\ max\{ t,dis_{1,i},dis_{j,t} \} \} \]

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
const int N=5e5+10;
const int M=N*2;
const int INF=0x3f3f3f3f;
int read()
{
	int x=0,f=0,c=getchar();
	while(c<'0'||c>'9'){if(c=='-') f=1;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
	return f?-x:x;
}

struct Edge
{
	int to,next,w;
}e[M];
int head[N],cnt;
void _add(int a,int b,int c){ e[++cnt]=(Edge){b,head[a],c}; head[a]=cnt;}
void add(int a,int b,int c){ _add(a,b,c); _add(b,a,c);}

int dep1[N],fa[N],dep2[N];
bool ond[N];
int st[N],tot;
int n,s,S,T;
int dfs1(int x)
{
	int ret=0;
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if(y==fa[x]) continue;
		fa[y]=x; dep1[y]=dep1[x]+e[i].w;
		int tmp=dfs1(y);
		if( dep1[tmp]>dep1[ret] || !ret) ret=tmp;
	}
	return ret?ret:x;//注意判断ret=0的情况 
}

int getd(int x)
{
	fa[x]=dep1[x]=0;
	return dfs1(x);
}

void dfs2(int x,int ff)
{
	for(int i=head[x];i;i=e[i].next)
	{
		int y=e[i].to;
		if(y==ff||ond[y]) continue;
		dfs2(y,x);
		dep2[x]=max(dep2[x],dep2[y]+e[i].w);
	}
}


int main()
{
	n=read(); s=read();
	for(int i=1;i<n;i++)
	{
		int x=read(),y=read(),z=read();
		add(x,y,z);
	}	
	S=getd(1); T=getd(S);
	for(int t=T;S!=t;t=fa[t]) ond[t]=1,st[++tot]=t;
	ond[S]=1; st[++tot]=S;
	int r=1,ret=0,ans=INF;
	for(int i=1;i<=tot;i++) dfs2(st[i],0);
	int t=0;
	for(int i=1;i<=tot;i++) t=max(t,dep2[st[i]]);	
	for(int l=1;l<=tot&&r!=tot;l++)
	{
		while(dep1[st[l]]-dep1[st[r+1]]<=s&&r!=tot) r++;//注意边界与取等号 
		int ret=max( dep1[T]-dep1[st[l]],dep1[st[r]]-dep1[S] );
		ret=max(ret,t);
		ans=min(ans,ret);
	}
	printf("%d\n",ans);
	return 0;
}

这里注意写法:
一种是右端点右移,直到>s
另一种是右端点右移,直到<=s 两种不同的写法应该要注意

重要性质: 直径中间的分叉一定不会比直径长
可以利用放缩来简化运算

posted @ 2022-01-16 14:45  __iostream  阅读(33)  评论(0)    收藏  举报