题目链接:https://www.luogu.org/problemnew/show/P2680
原先写的题,忘了补题解了。。。咕咕咕~~今天重新写了一遍,现在补上。
题意就是一棵树,我们要使得一条边的权值为0来达成题目给定的几条路径的最大长度最小。

就是当我们做最优解问题的时候,如果不好做,可以考虑从使用枚举答案然后将其转化为判定性问题。而答案的枚举采用二分来加速。(当然,这种最小化最大值的问题一眼应该就能看出来是二分了)

然后呢。。。当然,因为要求路径之间的长度,设路径的两端点分别为\(a,b\),那么\(dis(a,b)=dis(root,a)+dis(root,b)-2\times dis(root,lca(a,b))\)。

之后最大的问题就是这个check函数怎么写:

我们考虑二分出来一个长度\(k\),然后满足去掉一条边之后(也就是权值为0)所有的路径的长度都不超过它即为return true。当然如果不去掉任何一条边就可以满足条件的话肯定是return true。下面我们来处理如果有一些路径长度超过\(k\)的情况:

如果说有一些边超过\(k\),因为只能删去一个。所以我们肯定是要删去这些路径的交集上面的边才有可能满足return true的条件。而怎么判定一条边是不是在这些所有长度超出\(k\)的路径上呢,我们可以采取树上边差分的策略,开一个\(tot\)数组来记录(\(tot[i]\)表示节点\(i\)到它的父亲这条边),如果tot==这些路径的数量,就在交集上面了。

之后就没有什么了,代码如下:

#include<cstdio>
#include<algorithm>
#include<cstring>
#define MAXN 300010
using namespace std;
struct Edge{int to,nxt,w;}edge[MAXN<<1];
struct Node{int u,v,lcaa,diss;}node[MAXN<<1];
int summ,cnt=0,n,m,edge_number;
int num[MAXN],mi[MAXN],vis[MAXN];
int tot[MAXN],head[MAXN],deep[MAXN],dis[MAXN],lg[MAXN],fa[MAXN][32],dp[MAXN][32];
inline void add(int from,int to,int dis){edge[++edge_number].to=to;edge[edge_number].nxt=head[from];edge[edge_number].w=dis;head[from]=edge_number;
}
inline void init()
{for(int i=1;i<=n;i++)lg[i]=lg[i-1]+(1<<lg[i-1]==i);
}
inline void search(int x,int f)
{deep[x]=deep[f]+1;num[++cnt]=x;fa[x][0]=f;for(int i=1;(1<<i)<=deep[x];i++)fa[x][i]=fa[fa[x][i-1]][i-1];for(int i=head[x];i;i=edge[i].nxt){int v=edge[i].to;if(v==f) continue;dis[v]=dis[x]+edge[i].w;search(v,x);}
}
inline int lca(int x,int y)
{if(deep[x]<deep[y])  swap(x,y);while(deep[x]>deep[y])x=fa[x][lg[deep[x]-deep[y]]-1];if(x==y)  return x;for(int i=lg[deep[x]];i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];return fa[x][0];
}
inline bool check(int mid){int cnt=0,ans=0,maxx=0;memset(tot,0,sizeof(tot));for(int i=1;i<=m;i++){if(node[i].diss>mid){tot[node[i].u]++;tot[node[i].v]++;tot[node[i].lcaa]-=2;maxx=max(maxx,node[i].diss);cnt++;}}if(cnt==0) return true;for(int i=n;i>=1;i--) tot[fa[num[i]][0]]+=tot[num[i]];for(int i=2;i<=n;i++) if(tot[i]==cnt&&maxx-(dis[i]-dis[fa[i][0]])<=mid)return true;return false;
}
int main(){scanf("%d%d",&n,&m);for(int i=1;i<=n-1;i++){int x,y,w;scanf("%d%d%d",&x,&y,&w);add(x,y,w);add(y,x,w);summ+=w;}init();dis[1]=0;search(1,0);for(int i=1;i<=m;i++){scanf("%d%d",&node[i].u,&node[i].v);node[i].lcaa=lca(node[i].u,node[i].v);node[i].diss=dis[node[i].u]+dis[node[i].v]-2*dis[node[i].lcaa];}int left=0,right=summ;int mid;while(left<right){mid=(left+right)>>1;if(check(mid)) right=mid;else left=mid+1;}printf("%d",left);return 0;
}

转载于:https://www.cnblogs.com/fengxunling/p/9909619.html

[NOIP2015] 运输计划相关推荐

  1. BZOJ 4326 NOIP2015 运输计划(树上差分+LCA+二分答案)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MB Submit: 1388  Solved: 860 [Submit][Stat ...

  2. cogs2109 [NOIP2015] 运输计划

    cogs2109 [NOIP2015] 运输计划 二分答案+树上差分. STO链剖巨佬们我不会(太虚伪了吧 首先二分一个答案,下界为0,上界为max{路径长度}. 然后判断一个答案是否可行,这里用到树 ...

  3. 洛谷 2680 (NOIp2015) 运输计划

    题目:https://www.luogu.org/problemnew/show/P2680 因为是最长的时间最短,所以二分! 离线LCA可以知道路径长度.每次只看超过二分值的路径. 原本的想法是遍历 ...

  4. $Luogu2680/NOIp2015$ 运输计划

    传送门 $Sol$ 最暴力的做法就是枚举最长链上的边,然后再算一次所有的链长,更新$ans$. 这里要求最大的最小,容易想到二分答案.对于二分的值$mid$,扫一遍所有的链,若链长小于等于$mid$, ...

  5. 【图论】【LCA】NOIP2015运输计划

    分析: mmp出题人太垃圾了 尼玛树链剖分 O(Nlog2N) O ( N l o g 2 N ) O(Nlog^2N)的算法跑得飞快,用LCA严格 O(NlogN) O ( N l o g N ) ...

  6. 【Bzoj4326】运输计划

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MB Submit: 1091  Solved: 696 [Submit][Stat ...

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

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

  8. UOJ #150 【NOIP2015】 运输计划

    题目描述 公元 \(2044\) 年,人类进入了宇宙纪元. \(L\) 国有 \(n\) 个星球,还有 \(n-1\) 条双向航道,每条航道建立在两个星球之间,这 \(n-1\) 条航道连通了 \(L ...

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

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

  10. P2680 运输计划(树上差分+lca+二分)

    题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间 ...

最新文章

  1. 快速浏览Silverlight3 Beta:当HLSL遇上Silverlight
  2. 浅谈JDBC与ODBC的区别与应用
  3. C++11 正则表达式——实例1
  4. MariaDB 源码调试
  5. python题目及解析_python知识点总结以及15道题的解析
  6. 程序 峰谷值 提取_医学影像组学特征值(Radiomics Features)提取之Pyradiomics(一)理论篇...
  7. 学会这个技能,副业加 1 万不是问题,30 本理财秘籍免费领取(速领)
  8. 『ACM C++』 PTA 天梯赛练习集L1 | 016-017
  9. 查询一个表插入数据的时间,按BLOCK时间
  10. (Windbg调试一)minidump崩溃捕捉
  11. 11年的macbook还能用吗_8年老本的第二春:2011款Macbook Pro换血记
  12. CODESYS官方教程“您的第一个CODESYS程序”的一些注解
  13. python 转Excel二维表为一维表
  14. SpringBoot对接微信公众号,持续更新
  15. 《智能搜索和推荐系统》总结
  16. openstack搭建问题
  17. [UVA 10635] Prince ans Princess
  18. R语言学习记录:proc.time、Sys.time函数
  19. 【大数据分析专业毕设之基于python的手机销售大数据分析可视化系统】
  20. 空间中的语义直线检测_直线检测

热门文章

  1. 如何解决chm类型的文件在Windows操作系统中无法打开
  2. 包你满意的Git命令大全,快来收藏!
  3. 经典排序算法(十二)--地精排序Gnome Sort
  4. 05. 从尾到头打印链表(C++版本)
  5. 每天一道剑指offer-包含min函数的栈
  6. php制作调查问卷,用PHP制作饼图调查表
  7. springsecurity 登录失败_145-Spring Security
  8. python怎么样算安装好了_如何将安装好的Python
  9. (day 42 - 字符翻转 ) 剑指 Offer 58 - II. 左旋转字符串
  10. 八皇后问题-python描述