ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P2680 [NOIP2015 提高组] 运输计划 【二分+LCA+树上差分】

2022-08-27 00:30:43  阅读:148  来源: 互联网

标签:飞船 NOIP2015 运输 mid 航道 P2680 leq LCA 星球


题目描述

公元 \(2044\) 年,人类进入了宇宙纪元。

L 国有 \(n\) 个星球,还有 \(n-1\) 条双向航道,每条航道建立在两个星球之间,这 \(n-1\) 条航道连通了 L 国的所有星球。

小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 \(u_i\) 号星球沿最快的宇航路径飞行到 \(v_i\) 号星球去。显然,飞船驶过一条航道是需要时间的,对于航道 \(j\),任意飞船驶过它所花费的时间为 \(t_j\),并且任意两艘飞船之间不会产生任何干扰。

为了鼓励科技创新, L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小 P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。

在虫洞的建设完成前小 P 的物流公司就预接了 \(m\) 个运输计划。在虫洞建设完成后,这 \(m\) 个运输计划会同时开始,所有飞船一起出发。当这 \(m\) 个运输计划都完成时,小 P 的物流公司的阶段性工作就完成了。

如果小 P 可以自由选择将哪一条航道改造成虫洞, 试求出小 P 的物流公司完成阶段性工作所需要的最短时间是多少?

输入格式

第一行包括两个正整数 \(n, m\),表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 \(1\) 到 \(n\) 编号。

接下来 \(n-1\) 行描述航道的建设情况,其中第 \(i\) 行包含三个整数 \(a_i, b_i\) 和 \(t_i\),表示第 \(i\) 条双向航道修建在 \(a_i\) 与 \(b_i\) 两个星球之间,任意飞船驶过它所花费的时间为 \(t_i\)。

数据保证

接下来 \(m\) 行描述运输计划的情况,其中第 \(j\) 行包含两个正整数 \(u_j\) 和 \(v_j\),表示第 \(j\) 个运输计划是从 \(u_j\) 号星球飞往 \(v_j\)号星球。

输出格式

一个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间。

样例输入

6 3 
1 2 3 
1 6 4 
3 1 7 
4 3 6 
3 5 5 
3 6 
2 5 
4 5

样例输出

11

对于 \(100\%\) 的数据,保证:\(1 \leq a_i,b_i \leq n\),\(0 \leq t_i \leq 1000\),\(1 \leq u_i,v_i \leq n\)。


人话:给定一棵带点权的树,有 \(m\) 个从 \(u_i\) 到 \(v_i\) 的路径,让你将一条边变为 \(0\) ,使其路径最大值最小。

最大值最小,一听就是二分,考虑二分这个路径的最小值, 有什么可以 check 的性质吗?

首先我们可以预处理出 \(u_i\) 到 \(v_i\) 的经历的权值和,从大到小排个序,我们的 mid 肯定将这个有序之后的数组分为两部分,权值小于 mid 的部分和大于 mid 的部分。

小于 mid 的部分我们自然不同管他,因为它自然满足小于 mid 的限制,但大于 mid 的部分,我们需要在他们的交集边取一个最大值,减去最大的边权,判断这个值是否小于 mid 大于即使非法。

为什么要取交集?因为不是交集的边不能保证最大的减去它是合法情况且不能保证所有的大于 mid 的边都能减去这个值,所以必须取交集。

怎么取交集?树上边差分即可,边权化点权后,满足条件的点被覆盖的次数正好就是大于 mid 的边的个数,边差分维护就可以了。还有,边差分是 \(st[lca(u,v)]\) 减 \(2\) 捏,我真的服气我的记性了。

Code.

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+20;
struct node
{
	int u,v,lca,dis;
	bool operator < (const node &o) const {
		return dis > o.dis;
	}
} q[N];
int l,r,n,m,h[N],ne[N<<1],e[N<<1],w[N<<1],pl[N],idx,dep[N],top[N],sz[N],son[N],fa[N],res,st[N],yl[N];
void add(int u,int v,int c) {ne[++idx]=h[u],e[idx]=v,w[idx]=c,h[u]=idx;}
void dfs(int u,int father,int depth)
{
	dep[u]=depth; fa[u]=father; sz[u]=1;
	for(int i=h[u];~i;i=ne[i])
	{
		int j=e[i]; if(j == father) continue ;
		yl[j]=yl[u]+w[i]; pl[j]=w[i]; dfs(j,u,depth+1); sz[u]+=sz[j];
		if(sz[son[u]] < sz[j]) son[u]=j;
	}
}
void dfs2(int u,int t)
{
	top[u]=t; if(! son[u]) return ; dfs2(son[u],t);
	for(int i=h[u];~i;i=ne[i])
	{
		int j=e[i]; if(j == fa[u] || j == son[u]) continue ;
		dfs2(j,j);
	}
}
int lca(int u,int v)
{
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) swap(u,v);
		u=fa[top[u]];
	}
	return dep[u] < dep[v] ? u : v;
}
void dfs3(int u,int father)
{
	for(int i=h[u];~i;i=ne[i])
	{
		int j=e[i]; if(j == father) continue ;
		dfs3(j,u); st[u]+=st[j];
	}
}
bool check(int mid)
{
	int cnt=0,mx=0; memset(st,0,sizeof(int)*(n+10));
	for(int i=1;i<=m;i++)
	{
		if(q[i].dis <= mid) break;
		st[q[i].u]++; st[q[i].v]++; st[q[i].lca]-=2; cnt++;
	} dfs3(1,0);
	for(int i=1;i<=n;i++) if(st[i] == cnt) mx=max(mx,pl[i]);
	return q[1].dis-mx <= mid;
}
int main()
{
	memset(h,-1,sizeof h); scanf("%d%d",&n,&m);
	for(int i=1;i<n;i++)
	{
		int u,v,c; scanf("%d%d%d",&u,&v,&c); l=max(l,c);
		add(u,v,c); add(v,u,c); 
	} dfs(1,0,1); dfs2(1,1);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&q[i].u,&q[i].v);
		q[i].lca=lca(q[i].u,q[i].v); q[i].dis=yl[q[i].u]+yl[q[i].v]-yl[q[i].lca]*2;
	}
	stable_sort(q+1,q+1+m); r=q[1].dis; l=r-l;
	while(l <= r)
	{
		int mid = l + r >> 1;
		if(check(mid)) res=mid,r=mid-1;
		else l=mid+1;
	}
	printf("%d",res);
	return 0;
}

标签:飞船,NOIP2015,运输,mid,航道,P2680,leq,LCA,星球
来源: https://www.cnblogs.com/EastPorridge/p/16629645.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有