题目
简述题意:求直径的必须边。
首先,可通过两次,求出一条直径这里不赘述。
引理:两条直径必有公共点。
证明显然:
假设两条直径无公共点,那么由于树的连通性,我们在把这两条直径连起来一定更长,
与直径的最长性矛盾。
之后我们画图找一下,对于两条直径下的情况。
我们只要求一下满足第一种情况的深度最大值,再求出满足第二种情况的深度最小值,
,即为答案.特殊地,初始化.
这是否适用于所有情况呢?答案是显然的。
由于直径必交,而必须边的定义又是属于任意直径,
所以我们只要枚举直径上的点,看是否有合法分叉(能在直径中).
按照上面的求法,我们能保证不违反必须边的定义,同时最大,所以答案正确。
#include<map>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fir first
#define sec second
#define lc (x<<1)
#define rc (x<<1|1)
#define g getchar()
#define mk make_pair
#define pi pair<int,int>
using namespace std;
typedef long long ll;
const int N=2e5+10;
template<class o>void qr(o&x) {
char c=g;int f=1;x=0;
while(!isdigit(c)){if(c=='-')f=-1;c=g;}
while(isdigit(c))x=x*10+c-'0',c=g;
x*=f;
}
template<class o>void write(o x) {
if(x/10)write(x/10);
putchar(x%10+'0');
}
template<class o>void pri(o x) {
if(x<0)x=-x,putchar('-');
write(x);puts("");
}
int n,m,dep[N],fa[N];
ll d[N],f[N];
struct edge{int y,next,d;}a[N<<1];int len,last[N];
void ins(int x,int y,int d) {a[++len]=(edge){y,last[x],d};last[x]=len;}
void dfs(int x,int &t) {
f[x]=0;//d由上到下传递,f反之
for(int k=last[x],y,z;k;k=a[k].next) {
y=a[k].y; z=a[k].d; if(y==fa[x]) continue;
fa[y]=x; dep[y]=dep[x]+1; d[y]=d[x]+z;
dfs(y,t); if(d[y]>d[t]) t=y; f[x]=max(f[x],f[y]+z);
}
}
int u,v,p,q,sta[N],top;//直径有关信息:p,q为直径端点
bool in[N];
void find() {
for(int i=1;i<=n;i++) in[sta[i]]=1;
while(top) {
int x=sta[top--];
for(int k=last[x],y,z;k;k=a[k].next) {
y=a[k].y; z=a[k].d; if(in[y]) continue;
if(f[y]+z==f[x]) v=min(v,dep[x]);
if(f[y]+z==d[x]) u=max(u,dep[x]);
}
}
pri(v-u);
}
int main() {
qr(n);
for(int i=1,x,y,z;i<n;i++)
qr(x),qr(y),qr(z),ins(x,y,z),ins(y,x,z);
fa[1]=0; d[1]=0; dep[1]=1; dfs(1,p=1);
fa[p]=0; d[p]=0; dep[p]=1; dfs(p,q=p);
pri(d[q]); v=dep[q]; u=1;
do {
sta[++top]=q;
q=fa[q];
} while(q);
find(); return 0;
}