题目大意: 给你一棵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]运输计划的更多相关文章

  1. NOIP2015 提高组] 运输计划

    码农题啊兄弟们. 随便考虑二分一下,然后发现要取一条满足性质的边. 被所有大于\(mid\)的路径都覆盖,取了之后能把他们都弄到小于\(mid\) 那就树上差分再处理一下. 写了\(180h\),老年 ...

  2. [NOIP2015 提高组] 运输计划题解

    题目链接:P2680 [NOIP2015 提高组] 运输计划 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 看了好长时间题解才终于懂的,有关lca和二分答案的题解解释的不详细,一时 ...

  3. [NOIP 2015TG D2T3] 运输计划

    题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家 ...

  4. [NOIP2015提高组]运输计划

    题目:BZOJ4326.洛谷P2680.Vijos P1983.UOJ#150.codevs4632.codevs5440. 题目大意:有一棵带权树,有一些运输计划,第i个运输计划从ai到bi,耗时为 ...

  5. NKOJ 【NOIP2015 Day2】运输计划

    时间限制 : 20000 MS   空间限制 : 262144 KB 评测说明 : 2s,256m 问题描述 公元 2044 年,人类进入了宇宙纪元. L 国有 n 个星球,还有 n−1 条双向航道, ...

  6. NOIP2015 D2T3 运输计划

    拿到题目的第一眼 首先这是一棵n个节点的树(别说你看不出来) 然后对于树上的m条链我们可以选取树上的唯一一条边使它的边权变为0 求处理后最长链的长度 20分 m=1好啦,好像可做一眼望去全是水 只需求 ...

  7. 洛谷 P2680 [NOIP2015 提高组] 运输计划

    链接:P2680 题意: 在树上把一条边边权变为0使得最长给定路径最短 分析: 最大值最小可以想到二分答案,对于每一个mid,寻找所有大于mid的路径,再寻找是否存在一条边使得删去它后大于mid的路径 ...

  8. P2680 [NOIP2015 提高组] 运输计划 (树上差分-边差分)

    P2680 题目的大意就是走完m条路径所需要的最短时间(边权是时间), 其中我们可以把一条边的权值变成0(也就是题目所说的虫洞). 可以考虑二分答案x,找到一条边,使得所有大于x的路径都经过这条边(差 ...

  9. [NOIP 2015]运输计划-[树上差分+二分答案]-解题报告

    [NOIP 2015]运输计划 题面: A[NOIP2015 Day2]运输计划 时间限制 : 20000 MS 空间限制 : 262144 KB 问题描述 公元 2044 年,人类进入了宇宙纪元. ...

随机推荐

  1. python之web架构

    一.web架构简介 web.py是一个轻量级Python web框架,它简单而且功能强大.web.py是一个开源项目.该框架由已故美国作家.Reddit联合创始人.RSS规格合作创造者.著名计算机黑客 ...

  2. 从golang的垃圾回收说起(上篇)

    本文来自网易云社区 1 垃圾回收中的重要概念 1.1 定义 In computer science, garbage collection (GC) is a form of automatic me ...

  3. python 函数定义顺序

    #!/usr/bin/python # Hello World def order(): print("haha") print('Hello World!') order()

  4. 内置方法(item系列)

    class Foo: def __init__(self,name): self.name = name def __getitem__(self, item): # 获取时触发 print('get ...

  5. 使用.net 更新word目录

    方案一.采用OpenXml(服务器不依赖Office组件) 在word生成的最后加上代码: using (WordprocessingDocument docx = WordprocessingDoc ...

  6. Soliworks 2016建模细节总结(1)

    Soliworks 2016建模小细节总结(1) 1.Solidworks 2016三维建模的时候,如果想要在一个视图里面呈现出四个视图(包括三个独立的视图以及三维结构的实体模型图),可以直接按鼠标会 ...

  7. JVM--内存模型与线程

    一.硬件与效率的一致性 计算机的存储设备与处理器的运算速度存在几个数量级的差距,现在计算机系统不得不在内存和处理器之间增加一层高速缓存(cache)来作为缓冲.将运算需要的数据复制到缓存中,让运算能够 ...

  8. 397. Longest Continuous Increasing Subsequence

    Description Give an integer array,find the longest increasing continuous subsequence in this array. ...

  9. Github协作图想

    首先 git pull 从远程拉下代码,并在本地与本地代码自动合并 在本地解决冲突后,可将本地代码进行远程推送 版本库的Repository中存储的是版本树状链,每一根链接线代表每一次的修改,每一个节 ...

  10. BOM / URL编码解码 / 浏览器存储

    BOM 浏览器对象模型 BOM(Browser Object Model) 是指浏览器对象模型,是用于描述这种对象与对象之间层次关系的模型,浏览器对象模型提供了独立于内容的.可以与浏览器窗口进行互动的 ...