又一个被卡常的小朋友
查看原帖
又一个被卡常的小朋友
492662
Endt楼主2022/3/15 14:58

TLE95

#include<bits/stdc++.h>
using namespace std;

void dfs(int x); 
int lca(int x,int y,long long &w);
inline void solve(int x,int y,int f);
inline void f(int x);
inline bool check(long long t);

struct NODE{
	int fir,d,dp;
	int f[20];
	long long w[20];
}p[300005];
struct EDGE{
	int v,nxt;
	long long w;
}e[600005];
struct WORK{
	int u,v,f;
	long long w;
}a[300005];
int cmp(WORK x,WORK y){
	return x.w>y.w;
}

int cnt,tnc;
void add(int u,int v,long long w){
	++cnt;
	e[cnt].v=v;
	e[cnt].w=w;
	e[cnt].nxt=p[u].fir;
	p[u].fir=cnt;
}

int n,m;
int main(){
	long long summ=0;
	scanf("%d%d",&n,&m);
	for(int i=1;i<n;++i){
		int u,v;long long w;
		scanf("%d%d%lld",&u,&v,&w);
		summ+=w;
		add(u,v,w);
		add(v,u,w);
	}
	p[0].dp=-1;
	dfs(1);
	
	for(int i=1;i<=m;++i){
		int u,v,f;long long w;
		scanf("%d%d",&u,&v);
		f=lca(u,v,w);
		a[i].u=u,a[i].v=v,a[i].f=f,a[i].w=w;
	}
	sort(a+1,a+1+m,cmp);
	
	long long l=0ll,r=summ,m,ans;
	while(l<=r){
		m=l+r>>1;
		if(check(m)){
			ans=m;
			r=m-1;
		}else{
			l=m+1;
		}
	}
	printf("%lld",ans);
	
	return 0;
}

void dfs(int x){
	for(int i=1;i<=17;++i){
		p[x].f[i]=p[p[x].f[i-1]].f[i-1];
		p[x].w[i]=p[x].w[i-1]+p[p[x].f[i-1]].w[i-1];
	}
	for(int i=p[x].fir;i;i=e[i].nxt){
		int v=e[i].v;
		if(v==p[x].f[0])continue;
		p[v].f[0]=x;
		p[v].w[0]=e[i].w;
		p[v].dp=p[x].dp+1;
		dfs(v);
	}
}

int lca(int x,int y,long long &w){
	w=0;
    if(x==y)return x;
    if(p[x].dp<p[y].dp)swap(x,y);
    for(int i=17;i>=0;--i){
        if(p[p[x].f[i]].dp>=p[y].dp){
        	w+=p[x].w[i];
        	x=p[x].f[i];
        }
    }
    if(x==y)return x;
    for(int i=17;i>=0;--i){
        if(p[x].f[i]!=p[y].f[i]){
        	w+=p[x].w[i]+p[y].w[i];
        	x=p[x].f[i],y=p[y].f[i];
        }
    }
    w+=p[x].w[0]+p[y].w[0];
    return p[x].f[0];
}

inline void solve(int x,int y,int f){
	++p[x].d,++p[y].d;
	--p[f].d,--p[f].d;
}

inline void f(int x){
	for(int i=p[x].fir;i;i=e[i].nxt){
		int v=e[i].v;
		if(v==p[x].f[0])continue;
		f(v);
		p[x].d+=p[v].d;
	}
}

inline bool check(long long t){
	int c=0;
	for(int i=1;a[i].w>t;++i){
		solve(a[i].u,a[i].v,a[i].f);
		++c;
	}
	f(1);
	bool flag=0;
	for(int i=1;i<=n;++i){
		if(p[i].d==c){
			if(a[1].w-p[i].w[0]<=t)flag=1;
		}
		p[i].d=0;
	}
	return flag;
}
2022/3/15 14:58
加载中...