求调 马蜂良好
查看原帖
求调 马蜂良好
572133
潘德理2010楼主2025/6/30 21:17

提交记录

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,a[50050];
int re[50050],d[50050];// 是否为根节点的子节点 对应的副根 * 距离根节点距离  
int t[50050][25],s[50050][25];// i 向上 2^j 次到达的点 / 距离(不包括根节点)
int rb[50050];//点上是否有军队 
vector<pair<int,int> > e[50050];
vector<int> k[50050];
multiset<int> sa;
int le=0,ri=1e14+10,mid;//**
void dfs1(int u,int fa){
	if(u!=1&&re[u]!=1) t[u][0]=fa;
	for(int i=0;i<e[u].size();i++){
		int v=e[u][i].second,w=e[u][i].first;
		if(v==fa) continue;
		d[v]=d[u]+w;
		if(u!=1) s[v][0]=w;
		if(u==1) re[v]=1;
		dfs1(v,u);
	}
}
void ret(int x){
	if(x==1){
		sa.insert(mid);
		return ;
	}
	int pos=x,cd=mid;
	for(int j=20;j>=0;j--){
		if(!t[pos][j]) continue;
		if(s[pos][j]>cd) continue;
		cd-=s[pos][j];
		pos=t[pos][j];
	}
	if(re[pos]) k[pos].push_back(cd);
	else rb[pos]=1;
}
int dfs2(int u,int fa){
	if(rb[u]) return 1;
	int tg=0;
	for(int i=0;i<e[u].size();i++){
		int v=e[u][i].second;
		if(v==fa) continue;
		tg=1;
		int t1=dfs2(v,u);
		if(t1==0) return 0;
	}
	return tg;
}
signed main(){
	scanf("%lld",&n);
	for(int i=1;i<n;i++){
		int x,y,z;
		scanf("%lld%lld%lld",&x,&y,&z);
		e[x].push_back({z,y});
		e[y].push_back({z,x});
	}
	scanf("%lld",&m);
	for(int i=1;i<=m;i++){
		scanf("%lld",&a[i]);
	}
	dfs1(1,0);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=20;j++){
			t[i][j]=t[t[i][j-1]][j-1];
			s[i][j]=s[i][j-1]+s[t[i][j-1]][j-1];
		}
	}
	while(le<ri){
		sa.clear();
		memset(rb,0,sizeof(rb));
		for(auto &u:k) u.clear();
		mid=(le+ri)/2;
		for(int i=1;i<=m;i++){
			ret(a[i]);
		}
		vector<int> rg;
		for(int i=1;i<=n;i++){
			if(re[i]){
				sort(k[i].begin(),k[i].end(),greater<int>());
				int t1=dfs2(i,1);
				if(!t1){
					if(k[i].empty()){
						rg.push_back(i);
						continue;			
					}
					else{
						k[i].pop_back();
					}
				}
				for(int j=0;j<k[i].size();j++){
					int u=k[i][j];
					if(u<=d[i]) break;
					sa.insert(u-d[i]);
				}
			}
		}
		int ok=1;
		for(int i=0;i<rg.size();i++){
			int u=rg[i];
			auto it=sa.lower_bound(d[u]);
			if(it==sa.end()){
				ok=0;
				break;
			} 
			sa.erase(it);
		}
		if(ok==1) ri=mid;
		else le=mid+1;
	}
	if(le!=1e14+10) printf("%lld\n",le);
	else printf("-1\n");
}
2025/6/30 21:17
加载中...