玄关求条
查看原帖
玄关求条
1394167
li00000000a楼主2025/7/18 21:07
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
typedef pair<int,int> pii;
int n,m,dep[N],depth[N],f[30][N],lg[N*10],val[N];
int sigema;
vector<pii> G[N];
struct lian{
	int u,v,w,lcfa;
}sl[N];
bool cmp(lian x,lian y){
	return x.w<y.w;
}
void DFS(int pl,int fa){
	f[0][pl] = fa;
	for(auto edg:G[pl]){
		int v=edg.second,w=edg.first;
		if(v == fa) continue;
		dep[v] = dep[pl] + w;
		depth[v] = depth[pl]+1;
		DFS(v,pl);
	}
	for(int i=1;i<=lg[depth[pl]];i++) f[i][pl] = f[i-1][f[i-1][pl]];
}
int LCA(int u,int v){
	if(depth[u]<depth[v]) swap(u,v);//默认u大 
	int delta = depth[u]-depth[v];
	for(int i=0;i<=lg[delta];i++)
		if((1<<i)&delta) u = f[i][u];
	if(u==v) return u;
	for(int i=depth[u];i;i--){
		if(f[i][u] == f[i][v]) continue;
		u=f[i][u],v=f[i][v];
	}
	return f[0][u];
}
int ned,vec[N],cnt;
void dfs(int pl,int fa){//合并子节点权,判断能否删除该边 
	for(auto edg:G[pl]){
		int w = edg.first,v=edg.second;
		if(v == fa) continue;
		//printf("%d -> %d\n",pl,v);
		dfs(v,pl);
		val[pl] += val[v];
	}
	//printf("val[%d] = %d\n",pl,val[pl]);
	if(val[pl] == ned){
		for(auto x:G[pl]){
			int w=x.first,v = x.second;
			if(v == fa){
				vec[++cnt] = w;
				return;
			}
		}
	}
}
bool check(int x){
	int pla=0;
	for(int i=1;i<=m;i++)
		if(sl[i].w > x){//之后到链需要进行处理 
			pla = i;
			break;
		}
	if(!pla) return true;
	ned = m-pla+1;//有几条需要处理,被全部经过就可以删 
	//printf("have %d vertex needed to be dealt.\n",ned);
	for(int i=pla;i<=m;i++){
		val[sl[i].u]++;
		val[sl[i].v]++;
		val[sl[i].lcfa]-=2;
	}
	dfs(1,0);
	int red = 0;
	for(int i=1;i<=cnt;i++) red = max(red,vec[i]);
	//cout<<"\n"<<"\n";
	memset(val,0,sizeof(val));
	cnt = 0;
	bool flag = true;
	for(int i=pla;i<=m;i++)
		if(sl[i].w-red > x) flag = false;
	return flag;
}
int erfen(){
	int l=0,r=sigema,mid,ans=sigema; 
	while(l<=r){
		mid = (l+r)>>1;
		if(check(mid)){
			ans = min(ans,mid);//要让时间尽量小 
			r = mid-1;
		}else l = mid+1;
	}
	return ans;
}
signed main(){
	cin>>n>>m;
	for(int i=1;i<n;i++){
		int a,b,t;
		cin>>a>>b>>t;
		G[a].push_back({t,b});
		G[b].push_back({t,a});
		sigema += t;
	}
	dep[1]=0;
	depth[1]=0;
	lg[1]=0;
	for(int i=2;i<=N;i++) lg[i] = lg[i>>1]+1;
	DFS(1,0);
	//printf("finished DFS.\n");
	for(int i=1;i<=m;i++){
		int fr,to;
		cin>>fr>>to;
		int lca = LCA(fr,to);
		sl[i].u = fr,sl[i].v = to,sl[i].lcfa = lca;
		sl[i].w = dep[fr]-dep[lca] + dep[to]-dep[lca];
		//printf("[%d -> %d]:%d\n",sl[i].u,sl[i].v,sl[i].w);
	}
	//printf("have made the chain.\n");
	sort(sl+1,sl+m+1,cmp);//完成输入,知道链长 
	cout<<erfen()<<"\n";
	return 0;
}
2025/7/18 21:07
加载中...