[NOIP2015 TG D2T3]运输计划
题目大意: 给你一棵n个节点的树,有边权,有多个任务,每个要求从ui号节点到 vi号节点去。m 个计划, 这 m 个计划会同时开始。当这 m 个任务都完成时,工作完成。
现在可以把任意一个边的边权变为0,试求出完成工作所需要的最短时间是多少?
题解:先求出每个任务原来的所需时间,一种想法是枚举改变哪条边,但这肯定会超时(不然怎么是T3),然后我们可以想到,我们可以发现必须把最长的时间缩短,才可以把答案时间缩短,于是我们可以用二分它完成的时间,然后进行判断,把时间超过这个二分答案的任务记录一下,然后可以发现,我们要减少其中所有任务都经过的边才可以把所有任务的时间变短。
那该怎么做呢?就要用树上差分了(节点版),我们用一个数组存每个节点的差分值,它的子树的值的和就是它所要经过的次数,假设任务是从a->b,就可以s[a]++,s[b]++,s[lca(a,b)]-=2(lca要存下来,不然也会超时),具体可以baidu。
C++ Code:
#include<cstdio>
#include<cstring>
#define maxn 300100
#define maxm 21
#define inf 0x7ffffff
using namespace std;
int cnt,head[maxn];
int n,m,ans=inf;
int s[maxn],e[maxn];
int lca[maxn],deep[maxn],fa[maxn][maxm],sum[maxn],sum2[maxn];
int p[maxn];
struct Edge{
int to,nxt,cost;
}edge[maxn<<1];
void add(int a,int b,int c){
cnt++;
edge[cnt].to=b;
edge[cnt].nxt=head[a];
edge[cnt].cost=c;
head[a]=cnt;
}
void dfs(int root){
for (int i=head[root];i;i=edge[i].nxt){
int ne=edge[i].to;
if (deep[ne]==0){
deep[ne]=deep[root]+1;
sum[ne]=sum[root]+edge[i].cost;
fa[ne][0]=root;
dfs(ne);
}
}
}
void init(){
for (int i=1;i<maxm;i++){
for (int j=1;j<=n;j++){
fa[j][i]=fa[fa[j][i-1]][i-1];
}
}
}
int LCA(int x,int y){
if (deep[x]<deep[y])x^=y^=x^=y;
for (int i=maxm-1;i>=0;i--){
if (deep[fa[x][i]]>=deep[y]){
x=fa[x][i];
}
}
if (x==y)return x;
for (int i=maxm-1;i>=0;i--){
if (fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];
}
void dfs1(int root){
if (head[root]==0)return;
for (int i=head[root];i;i=edge[i].nxt){
int ne=edge[i].to;
if (deep[ne]==deep[root]+1){
dfs1(ne);
p[root]+=p[ne];
}
}
}
bool check(int mid){
int maxo=0,num=0;
memset(p,0,sizeof(p));
for (int i=1;i<=n;i++){
if (sum2[i]>mid){
num++;
if (maxo<(sum2[i]-mid))maxo=sum2[i]-mid;
p[s[i]]++;
p[e[i]]++;
p[lca[i]]-=2;
}
}
dfs1(1);
for (int i=1;i<=n;i++){
if (p[i]==num){
if (sum[i]-sum[fa[i][0]]>=maxo)return 1;
}
}
return 0;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<n;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
deep[1]=1;
dfs(1);
init();
int r=0;
for (int i=1;i<=m;i++){
scanf("%d%d",&s[i],&e[i]);
lca[i]=LCA(s[i],e[i]);
sum2[i]=(sum[s[i]]+sum[e[i]]-(sum[lca[i]]<<1));
if(sum2[i]>r)r=sum2[i];
}
int l=0;
while (l<=r){
int mid=l+r>>1;
if (check(mid)){
ans=mid;
r=mid-1;
}else{
l=mid+1;
}
}
printf("%d\n",ans);
return 0;
}
[NOIP2015 TG D2T3]运输计划的更多相关文章
- NOIP2015 提高组] 运输计划
码农题啊兄弟们. 随便考虑二分一下,然后发现要取一条满足性质的边. 被所有大于\(mid\)的路径都覆盖,取了之后能把他们都弄到小于\(mid\) 那就树上差分再处理一下. 写了\(180h\),老年 ...
- [NOIP2015 提高组] 运输计划题解
题目链接:P2680 [NOIP2015 提高组] 运输计划 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 看了好长时间题解才终于懂的,有关lca和二分答案的题解解释的不详细,一时 ...
- [NOIP 2015TG D2T3] 运输计划
题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家 ...
- [NOIP2015提高组]运输计划
题目:BZOJ4326.洛谷P2680.Vijos P1983.UOJ#150.codevs4632.codevs5440. 题目大意:有一棵带权树,有一些运输计划,第i个运输计划从ai到bi,耗时为 ...
- NKOJ 【NOIP2015 Day2】运输计划
时间限制 : 20000 MS 空间限制 : 262144 KB 评测说明 : 2s,256m 问题描述 公元 2044 年,人类进入了宇宙纪元. L 国有 n 个星球,还有 n−1 条双向航道, ...
- NOIP2015 D2T3 运输计划
拿到题目的第一眼 首先这是一棵n个节点的树(别说你看不出来) 然后对于树上的m条链我们可以选取树上的唯一一条边使它的边权变为0 求处理后最长链的长度 20分 m=1好啦,好像可做一眼望去全是水 只需求 ...
- 洛谷 P2680 [NOIP2015 提高组] 运输计划
链接:P2680 题意: 在树上把一条边边权变为0使得最长给定路径最短 分析: 最大值最小可以想到二分答案,对于每一个mid,寻找所有大于mid的路径,再寻找是否存在一条边使得删去它后大于mid的路径 ...
- P2680 [NOIP2015 提高组] 运输计划 (树上差分-边差分)
P2680 题目的大意就是走完m条路径所需要的最短时间(边权是时间), 其中我们可以把一条边的权值变成0(也就是题目所说的虫洞). 可以考虑二分答案x,找到一条边,使得所有大于x的路径都经过这条边(差 ...
- [NOIP 2015]运输计划-[树上差分+二分答案]-解题报告
[NOIP 2015]运输计划 题面: A[NOIP2015 Day2]运输计划 时间限制 : 20000 MS 空间限制 : 262144 KB 问题描述 公元 2044 年,人类进入了宇宙纪元. ...
随机推荐
- python之web架构
一.web架构简介 web.py是一个轻量级Python web框架,它简单而且功能强大.web.py是一个开源项目.该框架由已故美国作家.Reddit联合创始人.RSS规格合作创造者.著名计算机黑客 ...
- 从golang的垃圾回收说起(上篇)
本文来自网易云社区 1 垃圾回收中的重要概念 1.1 定义 In computer science, garbage collection (GC) is a form of automatic me ...
- python 函数定义顺序
#!/usr/bin/python # Hello World def order(): print("haha") print('Hello World!') order()
- 内置方法(item系列)
class Foo: def __init__(self,name): self.name = name def __getitem__(self, item): # 获取时触发 print('get ...
- 使用.net 更新word目录
方案一.采用OpenXml(服务器不依赖Office组件) 在word生成的最后加上代码: using (WordprocessingDocument docx = WordprocessingDoc ...
- Soliworks 2016建模细节总结(1)
Soliworks 2016建模小细节总结(1) 1.Solidworks 2016三维建模的时候,如果想要在一个视图里面呈现出四个视图(包括三个独立的视图以及三维结构的实体模型图),可以直接按鼠标会 ...
- JVM--内存模型与线程
一.硬件与效率的一致性 计算机的存储设备与处理器的运算速度存在几个数量级的差距,现在计算机系统不得不在内存和处理器之间增加一层高速缓存(cache)来作为缓冲.将运算需要的数据复制到缓存中,让运算能够 ...
- 397. Longest Continuous Increasing Subsequence
Description Give an integer array,find the longest increasing continuous subsequence in this array. ...
- Github协作图想
首先 git pull 从远程拉下代码,并在本地与本地代码自动合并 在本地解决冲突后,可将本地代码进行远程推送 版本库的Repository中存储的是版本树状链,每一根链接线代表每一次的修改,每一个节 ...
- BOM / URL编码解码 / 浏览器存储
BOM 浏览器对象模型 BOM(Browser Object Model) 是指浏览器对象模型,是用于描述这种对象与对象之间层次关系的模型,浏览器对象模型提供了独立于内容的.可以与浏览器窗口进行互动的 ...