[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 年,人类进入了宇宙纪元. ...
随机推荐
- Please ensure JDK installation is valid and compatible with the current OS
报错如下: Gradle sync failed: Could not run JVM from the selected JDK. Please ensure JDK installation is ...
- Redis系列七 主从复制(Master/Slave)
主从复制(Master/Slave) 1.是什么 也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主. 2 ...
- myeclipse 配置堆内存
2.非堆内存分配 JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64:由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4. 打开myeclipse ...
- Java开发工程师(Web方向) - 01.Java Web开发入门 - 第5章.Git
第5章--Git 版本控制简介 VCS (version control system) 版本控制系统:记录若干文件的修订记录的系统,帮助查阅/回到某个历史版本 LVCS本地 CVCS集中式(Cent ...
- CodeForces - 1059D(二分+误差)
链接:CodeForces - 1059D 题意:给出笛卡尔坐标系上 n 个点,求与 x 轴相切且覆盖了所有给出点的圆的最小半径. 题解:二分半径即可.判断:假设当前二分到的半径是 R ,因为要和 x ...
- CodeForces - 776C(前缀和+思维)
链接:CodeForces - 776C 题意:给出数组 a[n] ,问有多少个区间和等于 k^x(x >= 0). 题解:求前缀和,标记每个和的个数.对每一个数都遍历到1e5,记录到答案. # ...
- 大理石在哪儿 (Where is the Marble?,UVa 10474)
题目描述:算法竞赛入门经典例题5-1 #include <iostream> #include <algorithm> using namespace std; ; int m ...
- 利用maven进行项目管理
下面为maven项目管理的一个结构 首先pom是路径文件,我们在编译或是运行程序时调用到jdk或一些自己写的jar包时会需要指明物理路径,这里的pom是一样的道理,同时在maven的管理下多出来了一些 ...
- @meida 媒体查询
示例 @meida 媒体查询 在进行书写的时候需要考虑到加载顺序和样式权重使用meida响应式实现不同宽度布局示例 常用工具 https://mydevice.io 参考链接 https://deve ...
- bug 调试
系统性能分析中,CPU.内存和 IO 是主要关注项.----系统层面 1. 对于 CPU,如果是常见的 Linux,可以先用 top 命令查看负载状况. top -H -p [pid] pstree ...