CF1881F Minimum Maximum Distance

原题链接

这题可以换根 dp,可以 dfs 序加线段树,但是还以一种更简便的做法,直接求两端都是标记点的最长路径就可以了。若路径长度是 \(L\),则答案是 \(\left\lceil\frac{L}{2}\right\rceil\)。具体做法就是和求直径一样,两次 dfs 即可。

  • 至于为什么,其实很简单。设这条路径两个端点分别为 \(u,v\)。考虑不在这条路径上的点 \(i\),\(f_i\) 一定是先到路径上的某一点 \(x\) 的距离,再加上 \(f_x\),一定不会更优。
  • 接着考虑在路径上的点 \(x\)。如果 \(x\) 距离 \(u\) 更近,那么 \(f_x=dist_{x,v}\)。反之亦然。显然只有取路径中点的时候最优,此时路径被分成两半,但 \(L\) 不一定是偶数,并且 \(f_x\) 应取最大值,所以要记得上取整。故最后答案为 \(\left\lceil\frac{L}{2}\right\rceil\)。
  • 最后别忘了特判只有一个标记点的情况,答案应为 \(0\)。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<utility>
#include<vector>
#include<queue>
#include<bitset>
#include<map>
#define FOR(i,a,b) for(register int i=a;i<=b;i++)
#define ROF(i,a,b) for(register int i=a;i>=b;i--)
#define mp(a,b) make_pair(a,b)
#define pll pair<long long,long long>
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
inline int read();
typedef long long ll;
typedef double db;
const int N=2e5+5;
const int INF=0x3f3f3f3f;
int n,m,k;
int mark[N];
struct E{
	int to,nex;
}edge[N<<1];
int head[N],cnt=0;
void add(int u,int v){
	edge[++cnt]=(E){v,head[u]};
	head[u]=cnt;
}
int c,L=0;
int dist[N];
void dfs(int u,int fa){
	for(int i=head[u];i;i=edge[i].nex){
		int v=edge[i].to;
		if(v==fa) continue;
		dist[v]=dist[u]+1;
		dfs(v,u);
		if(mark[v]&&dist[v]>dist[c]) c=v;
	}
}
int main()
{
	int T=read();
	while(T--){
		n=read(),k=read();
		memset(mark,0,sizeof mark);
		memset(head,0,sizeof head);
		memset(dist,0,sizeof dist);
		cnt=0;
		FOR(i,1,k)
			mark[read()]=1;
		FOR(i,1,n-1){
			int u=read(),v=read();
			add(u,v);add(v,u);
		}
		if(k==1){
			puts("0");
			continue;
		}
		FOR(i,1,n){
			if(mark[i]){
				dist[i]=0;
				L=0;
				c=0;
				dfs(i,0);
				break;
			}
		}
		dist[c]=0;
		dfs(c,0);
		L=dist[c];
		printf("%d\n",(L+1)/2);
	}
	return 0;
}


inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
	return f*x;
}
posted @ 2023-10-13 21:43  LHLeisus  阅读(77)  评论(0)    收藏  举报