#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10;
int f[N][22],dis[N],root = 1,dep[N],n,m,cha[N],sum[N];
typedef pair<int,int> P;
struct line{
int x,y,l,dis;
}road[N];
inline int read()
{
int p=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){p=p*10+c-'0';c=getchar();}
return f*p;
}
vector<P> v[N];
void dfs1(int s,int d){
dep[s] = d;
for(int i = 0;i<v[s].size();++i){
int to = v[s][i].first,w = v[s][i].second;
if(to!=f[s][0]){
sum[to] = w;
f[to][0] = s;
dis[to] = dis[s] + w;
dfs1(to,d+1);
}
}
}
inline int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i = 0;i<22;++i){
if(((dep[x]-dep[y])>>i)&1){
x = f[x][i];
}
}
if(x==y)return x;
for(int i = 21;i>=0;--i){
if(f[x][i]!=f[y][i]){
x = f[x][i];
y = f[y][i];
}
}
return f[x][0];
}
bool cmp(line &a,line &b){
return a.dis>b.dis;
}
void dfs2(int s){
for(int i = 0;i<v[s].size();++i){
int to = v[s][i].first ,w = v[s][i].second;
if(f[s][0]!=to){
dfs2(to);
cha[s] += cha[to];
}
}
}
inline bool pd(int mid){
for(int i = 1;i<=n;++i)cha[i] = 0;
int cnt = 0;
for(int i = 1;i<=m;++i){
if(road[i].dis>mid){
++cnt;
cha[road[i].x]++;
cha[road[i].y]++;
cha[road[i].l]-=2;
}
else break;
}
dfs2(root);
for(int i = 2;i<=n;++i){
if(cha[i]==cnt&&road[1].dis - sum[i]<=mid){
return 1;
}
}
return 0;
}
int main(){
IOS;
//freopen("a.txt","r",stdin);
n = read();
m = read();
for(int i = 1;i<=n-1;++i){
int x,y,z;
x = read();
y = read();
z = read();
v[x].push_back(P(y,z));
v[y].push_back(P(x,z));
}
dfs1(root,1);
for(int j = 1;j<22;++j){
for(int i = 1;i<=n;++i){
f[i][j] = f[f[i][j-1]][j-1];
}
}
for(int i = 1;i<=m;++i){
int x,y,l;
x = read();
y = read();
l = lca(x,y);
road[i].x = x;
road[i].y = y;
road[i].l = l;
road[i].dis = dis[x]+dis[y]-2*dis[l];
}
sort(road+1,road+1+m,cmp);
int l = 0,r = road[1].dis;
// 最小化最大值
while(l<r){
int m = (l+r)>>1;
if(pd(m)){
r = m;
}
else{
l = m + 1;
}
}
cout<<r<<endl;
return 0;
}
下面是题解的 120ms 我的2s这是怎么回事
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define re register
using namespace std;
typedef long long ll;
const int inf=1e9+7;
inline int read()
{
int p=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){p=p*10+c-'0';c=getchar();}
return f*p;}
const int maxn=300003;
struct Edge
{
int from,to,w,id;
}p[maxn<<1];
struct query
{
int x,y,lca,d;
}A[maxn];
int n,m,cnt,head[maxn<<1],C[maxn],dis[maxn];
int fa[maxn],depth[maxn],top[maxn],heavy[maxn],size[maxn];
int val[maxn],dnf[maxn],tot,R,L;
inline void add_edge(int x,int y,int W)//加边
{
cnt++;
p[cnt].from=head[x];
head[x]=cnt;
p[cnt].to=y;
p[cnt].w=W;
}
inline void dfs1(int x,int f)
//树剖dfs1:处理每个点的父亲fa,深度depth,子树大小size,dfs序dnf
{
fa[x]=f,depth[x]=depth[f]+1,size[x]=1,dnf[++tot]=x;
for(re int i=head[x];i;i=p[i].from)
{
int y=p[i].to;
if(y==f)continue;
val[y]=p[i].w;
dis[y]=dis[x]+p[i].w;
dfs1(y,x);
size[x]+=size[y];
if(!heavy[x]||size[y]>size[heavy[x]])
heavy[x]=y;
}
}
inline void dfs2(int x,int t)//树剖dfs2:处理重链
{
top[x]=t;
if(!heavy[x])return ;
dfs2(heavy[x],t);
for(re int i=head[x];i;i=p[i].from)
{
int y=p[i].to;
if(y==fa[x]||y==heavy[x])continue;
dfs2(y,y);
}
}
inline int LCA(int x,int y)//树剖求LCA
{
while(top[x]!=top[y])
{
if(depth[top[x]]<depth[top[y]])swap(x,y);
x=fa[top[x]];
}
return depth[x]<=depth[y]?x:y;
}
//=================================以上是树剖常规操作
inline int check(int lim,int sum=0)//二分答案检验,如上所述
{
memset(C,0,sizeof(C));//注意每一次都要清空C数组
for(re int i=1;i<=m;i++)
if(A[i].d>lim)//树上(边)差分
{
C[A[i].x]++,C[A[i].y]++,C[A[i].lca]-=2;
sum++;
}
for(re int i=n;i>=1;i--)
{
C[fa[dnf[i]]]+=C[dnf[i]];//每次差分值都累加到父亲节点
if(val[dnf[i]]>=R-lim&&C[dnf[i]]==sum)
//存在一条路径满足上述条件则可行
return 1;
}
return 0;//否则无解
}
inline int Binary_search(int llim,int rlim,int mid=0)//二分答案
{
while(llim<rlim)
{
mid=(llim+rlim)>>1;
if(check(mid))rlim=mid;
else llim=mid+1;
}
return llim;
}
int main()
{
// freopen("transport.in","r",stdin);
// freopen("transport.out","w",stdout);
//这是校内模拟赛的考试题= =光荣爆蛋
n=read(),m=read();
for(re int i=1;i<n;i++)
{
int x=read(),y=read(),w=read();
add_edge(x,y,w);
add_edge(y,x,w);
L=max(L,w);//统计最大边权
}
dfs1(1,0);dfs2(1,1);//树剖预处理
for(re int i=1;i<=m;i++)//预处理每一次请求的lca和距离
{
A[i].x=read(),A[i].y=read();
A[i].lca=LCA(A[i].x,A[i].y);
A[i].d=dis[A[i].x]+dis[A[i].y]-2*dis[A[i].lca];
R=max(R,A[i].d);
}
printf("%d\n",Binary_search(R-L,R+1));//二分答案
return 0;
}