运输计划sol

运输计划
最小化最大值问题,考虑用二分答案
check中一般用贪心策略
将每条路径的长度预处理,对二分的ans,将长度比ans大的取出来
并找出这些路径是否有一条重边使得最长的路径减了这条边后小于ans
注意dfs中参数少一点会更快,将dfs中访问顺序存到数组中,在每次check时不要再次dfs
数组要开大一点。。

#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define SZ(x) ((int)x.size())
#define ALL(x) x.begin(),x.end()
#define U(i,u) for(register ll i=head[u];i;i=nxt[i])
#define rep(i,a,b) for(register ll i=(a);i<=(b);++i)
#define per(i,a,b) for(register ll i=(a);i>=(b);--i)
using namespace std;
typedef long double ld;
typedef long long ll;
typedef unsigned int ui;
typedef pair<int,int> PII;
typedef vector<int> VI;
template<class T> inline void read(T &x){
	x=0;char c=getchar();ll f=1;
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=f;
}
template<class T> inline void cmin(T &x, T y){x=x<y?x:y;}
template<class T> inline void cmax(T &x, T y){x=x>y?x:y;}
const int N=1000100;
ll n,m,head[N],nxt[N],v[N],cnt,uu[N],vi[N],li[N],anc[N][24];
ll w[N],su,mx,mxx,mi=9999999999,s[N],dep[N];
ll num[N],ct;
ll vis[N],tmp;
inline void add(ll x,ll y,ll z){nxt[++cnt]=head[x];head[x]=cnt;v[cnt]=y;w[cnt]=z;}
inline void dfs(ll now,ll d){
	vis[now]=1;num[++ct]=now;dep[now]=d;U(i,now){
		if(vis[v[i]])continue;s[v[i]]=s[now]+w[i];anc[v[i]][0]=now;dfs(v[i],d+1);
	}
}
inline void init(){
	memset(vis,0,sizeof(vis));dfs(1,0);
	rep(j,1,23)rep(i,2,n){anc[i][j]=anc[anc[i][j-1]][j-1];}
}
inline void swim(ll &x,ll h){
	for(ll i=0;h;i++){
		if(h&1)x=anc[x][i];
		h>>=1;
	}
}
inline ll lca(ll x,ll y){
	if(dep[x]<dep[y])swap(x,y);
	if(y==1)return 1;
	swim(x,dep[x]-dep[y]);
	if(x==y)return x;
	for(ll i=23;i>=0;i--){
		if(anc[x][i]^anc[y][i]){
			x=anc[x][i];y=anc[y][i];
		}
	}
	return anc[x][0];
}
inline bool check(ll an){
	memset(vis,0,sizeof(vis));
	tmp=0;rep(i,1,m){
		if(dep[i]>an){
			++vis[uu[i]],++vis[vi[i]],vis[li[i]]-=2;
			++tmp;
		}
	}
	if(!tmp)return 1;
	per(i,n,2)vis[anc[num[i]][0]]+=vis[num[i]];
	rep(i,1,n)if(vis[i]>=tmp&&mx-(s[i]-s[anc[i][0]])<=an)return 1;
	return 0;
}
int main(){
	read(n);read(m);ll a,b;ll c;rep(i,1,n-1){read(a);read(b);read(c);add(a,b,c);add(b,a,c);su+=c;cmax(mxx,c);}
	init();rep(i,1,m){read(uu[i]);read(vi[i]);li[i]=lca(uu[i],vi[i]);}
	rep(i,1,m){dep[i]=s[vi[i]]+s[uu[i]]-2*s[li[i]];cmax(mx,dep[i]);cmin(mi,dep[i]);}
	ll l=0,r=su,mid;
	while(r-l>=3){
		mid=(r+l)>>1;if(check(mid))r=mid;else l=mid+1;
	}
	for(ll i=l;i<=r;i++){
		if(check(i)){
			printf("%lld\n",i);
			return 0;
		}
	}
	return 0;
}
/*
6 3 
1 2 3 
1 6 4 
3 1 7
4 3 12
3 5 5 
3 6 
2 5 
4 5
*/

猜你喜欢

转载自www.cnblogs.com/hangzz/p/13387282.html