【uoj150】 NOIP2015—运输计划
http://uoj.ac/problem/150 (题目链接)
题意
给出一棵树以及m个询问,可以将树上一条边的权值修改为0,求经过这样的修改之后最长的边最短是多少。
Solution
老早就听说过这道题了,好像使用树链剖分。
先树链剖分求出每个询问的路程,最长的最短,可以用二分做。二分最长的边的大小,也就是最后的答案,问题来了,怎么判断这个答案是否可行呢?
我们记录下所有超出当前答案的询问的个数p,用d记录下符合条件的边比当前二分的答案最大大多少,并给所有询问的两端点u,v的sum[]加上1,给他们的最近公共祖先f的sum[]减去2。这样做有什么用呢?这样就可以统计每条边经过了多少次了。
我们通过dfs,每经过一条边i,就把cnts[i]加上当前节点的sum值,这就代表有多少个点会经过这条边,回溯的时候更新sum即可。
最后的时候如果存在一条边被经过的次数正好等于当前询问数p,并且这条边的长度大于等于d,那么就是合法的,否则不合法。
其实这样的话根本就不用写树链剖分,dfs一遍就可以记录两点间距离了。。。然而树链剖分版不知道为什么最后uoj上extra test被卡的爆空间了。。好像是爆栈,于是手动开无限栈,MLE?!而且读入优化也gi了,真的鬼畜。。。无奈最后换成dfs版,没想到TLE。。。为什么bzoj上就能AC捏。
细节
差分的时候计数器数组cnts开成边数的空间。
代码
// uoj150
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define pragma comment(linker,"/STACK:1024000000,1024000000")
#define LL long long
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;
int getint() {
int f=1,x=0;char ch=getchar();
while (ch<='0' || ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
return x*f;
} const int maxn=300010;
struct edge {int w,to,next;}e[maxn<<1];
struct ask {int u,v,dis;}q[maxn];
int bin[30],fa[maxn][30],head[maxn],deep[maxn],sum[maxn],d[maxn],cnts[maxn<<1];
int n,m,cnt,num; void link(int u,int v,int w) {
e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].w=w;
e[++cnt].to=u;e[cnt].next=head[v];head[v]=cnt;e[cnt].w=w;
}
void dfs1(int x) {
for (int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa[x][0]) {
d[e[i].to]=d[x]+e[i].w;
deep[e[i].to]=deep[x]+1;
fa[e[i].to][0]=x;
dfs1(e[i].to);
}
}
int lca(int x,int y) {
if (deep[x]<deep[y]) swap(x,y);
int t=deep[x]-deep[y];
for (int i=0;bin[i]<=t;i++) if (t&bin[i]) x=fa[x][i];
for (int i=20;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return x==y?x:fa[x][0];
}
void dfs(int x) {
for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa[x][0]) {
dfs(e[i].to);
sum[x]+=sum[e[i].to];
cnts[i]=sum[e[i].to];
}
}
bool check(int mid) {
int d=0,p=0;
memset(sum,0,sizeof(sum));
for (int u=q[1].u,v=q[1].v,i=1;i<=n;i++,u=q[i].u,v=q[i].v)
if (q[i].dis>mid) {
sum[u]++;sum[v]++;
sum[lca(u,v)]-=2;
p++;
d=max(d,q[i].dis-mid);
}
dfs(1);
for (int i=1;i<=cnt;i++) if (p==cnts[i] && e[i].w>=d) return 1;
return 0;
}
int main() {
bin[0]=1;for (int i=1;i<=20;i++) bin[i]=bin[i-1]<<1;
scanf("%d%d",&n,&m);
for (int u,v,w,i=1;i<n;i++) {
scanf("%d%d%d",&u,&v,&w);
link(u,v,w);
}
dfs1(1);
int L=0,R=-inf,ans=0;
for (int u,v,i=1;i<=m;i++) {
q[i].u=u=getint(),q[i].v=v=getint();
int f=lca(u,v);
q[i].dis=d[u]+d[v]-2*d[f];
R=max(q[i].dis,R);
}
while (L<=R) {
int mid=(L+R)>>1;
if (check(mid)) {ans=mid;R=mid-1;}
else L=mid+1;
}
printf("%d",ans);
return 0;
}
【uoj150】 NOIP2015—运输计划的更多相关文章
- bzoj 4326: NOIP2015 运输计划
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MB Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个 ...
- NOIP2015 运输计划(bzoj4326)
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 886 Solved: 574[Submit][Status] ...
- [BZOJ4326][codevs4632][codevs5440][UOJ#150][NOIP2015]运输计划
[BZOJ4326][codevs4632][codevs5440][UOJ#150][NOIP2015]运输计划 试题描述 公元 2044 年,人类进入了宇宙纪元. L 国有 n 个星球,还有 n− ...
- [NOIP2015]运输计划 D2 T3 LCA+二分答案+差分数组
[NOIP2015]运输计划 D2 T3 Description 公元2044年,人类进入了宇宙纪元. L国有n个星球,还有n-1条双向航道,每条航道建立在两个星球之间,这n-1条航道连通了L国的所有 ...
- NOIP2015 运输计划(二分+LCA+差分)
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 308 Solved: 208[Submit][Status] ...
- 数据结构(树链剖分):COGS 2109. [NOIP2015] 运输计划
2109. [NOIP2015] 运输计划 ★★★ 输入文件:transport.in 输出文件:transport.out 简单对比时间限制:1 s 内存限制:256 MB [题目描 ...
- BZOJ 4326 NOIP2015 运输计划 (二分+树上差分)
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1930 Solved: 1231[Submit][Statu ...
- cogs2109 [NOIP2015] 运输计划
cogs2109 [NOIP2015] 运输计划 二分答案+树上差分. STO链剖巨佬们我不会(太虚伪了吧 首先二分一个答案,下界为0,上界为max{路径长度}. 然后判断一个答案是否可行,这里用到树 ...
- LOJ2425 NOIP2015 运输计划 【二分+LCA+树上差分】*
LOJ2425 NOIP2015 运输计划 LINK 题意:给你一颗树,可以将任意一条边的权值变成0,然后求m条路径的长度的最小值 思路: 先二分最后的距离ans,然后我们把路程大于ans的所有路径拿 ...
- AC日记——[NOIP2015]运输计划 cogs 2109
[NOIP2015] 运输计划 思路: 树剖+二分: 代码: #include <cstdio> #include <cstring> #include <iostrea ...
随机推荐
- 转: Github访问慢解决办法
from: https://yq.aliyun.com/articles/36744 Github访问慢解决办法 zxiaofan 2016-04-20 17:25:00 浏览2156 评论0 摘 ...
- Mac必装app-持续更新
所有软件都是免费,或者有破解版 都可以在google上***for mac 搜索到 Google Chrome Microsoft Office Evernote Skype Alfred AppCl ...
- poj 1050 To the Max
To the Max Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 45906 Accepted: 24276 Desc ...
- 研:手势与眼动相结合-手势SDK的整合
Leap提供了SDK.但是整合有很多的问题,写博客记录一下: 写一个类:SampleListener.cpp以及头文件SampleListener.h. 这里主要碰到的问题是找不到以及冲突问题: 这里 ...
- 26Mybatis_一级缓存及其测试
这篇文章讲解一级缓存: 先介绍一级缓存的原理:
- Google play billing(Google play 内支付)
准备工作 1. 通过Android SDK Manager下载extras中的Google Play services和Google Play Billing Library两个包. 2. 把下载的. ...
- 如何免费访问Google?
访问Google方法(以Mac为例) 1.替换hosts文件中的内容,文件链接如下: https://github.com/racaljk/hosts 2.下载Google浏览器,链接如下: http ...
- ruby 元编程
一 对象模型 kernel Module Kernel.private_instance_methods.grep(/^pr/) private method 1 如果一个方法接收者不是你自己,一 ...
- C++ c++与C语言的区别(实用性增强,register关键字增强,全局变量检测增强)
//区别①:实用性增强 #include<iostream> using namespace std; //C语言中的变量都必须在作用域开始的位置定义!! //C++中更强调语言的“实用性 ...
- log4j发送邮件乱码
Log4J发日志邮件给多个接收者及标题.正文乱码问题 以前开发的系统没有单独的日志管理,所有的日志统一输出到tomcat后台一个文件里,不几天就是好几G,现在要整体增加一个Log4J管理日志的功能,其 ...