NOIP2015运输计划(二分答案)
题目描述
公元2044年,人类进入了宇宙纪元。
L国有n个星球,还有n-1条双向航道,每条航道建立在两个星球之间,这n-1条航道连通了L国的所有星球。
小P掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从ui号星球沿最快的宇航路径飞行到vi号星球去。显然,飞船驶过一条航道是需要时间的,对于航道j,任意飞船驶过它所花费的时间为tj,并且任意两艘飞船之间不会产生任何干扰。
为了鼓励科技创新,L国国王同意小P的物流公司参与L国的航道建设,即允许小P把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。
在虫洞的建设完成前小P的物流公司就预接了m个运输计划。在虫洞建设完成后,这m个运输计划会同时开始,所有飞船一起出发。当这m个运输计划都完成时,小P的物流公司的阶段性工作就完成了。
如果小P可以自由选择将哪一条航道改造成虫洞,试求出小P的物流公司完成阶段性工作所需要的最短时间是多少?
输入格式
第一行包括两个正整数n、m,表示L国中星球的数量及小P公司预接的运输计划的数量,星球从1到n编号。
接下来n-1行描述航道的建设情况,其中第i行包含三个整数ai, bi和ti,表示第i条双向航道修建在ai与bi两个星球之间,任意飞船驶过它所花费的时间为ti。
接下来m行描述运输计划的情况,其中第j行包含两个正整数uj和vj,表示第j个运输计划是从uj号星球飞往vj号星球。
输出格式
共1行,包含1个整数,表示小P的物流公司完成阶段性工作所需要的最短时间。
input
6 3
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5
output
11
样例说明
将第1条航道改造成虫洞:则三个计划耗时分别为:11、12、11,故需要花费的时间为12。
将第2条航道改造成虫洞:则三个计划耗时分别为:7、15、11,故需要花费的时间为15。
将第3条航道改造成虫洞:则三个计划耗时分别为:4、8、11,故需要花费的时间为11。
将第4条航道改造成虫洞:则三个计划耗时分别为:11、15、5,故需要花费的时间为15。
将第5条航道改造成虫洞:则三个计划耗时分别为:11、10、6,故需要花费的时间为11。
故将第3条或第5条航道改造成虫洞均可使得完成阶段性工作的耗时最短,需要花费的时间为11。
限制与约定
解题思路:
首先考虑一下暴力,在n,m都小于3000时,先将两点间的边权值转化为深度较大的点的权值,利用朴素LCA求出两点间的耗费时间,再枚举删去哪一点枚举m中答案,更新即可
时间复杂度O(n*m),期望得分60分
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long lnt;
struct pnt{
int hd;
int no;
int fa;
int ol;
int dp;
lnt val;
}p[];
struct ent{
int twd;
int lst;
lnt tim;
}e[];
int cnt;
int n,m;
lnt ans=0x7f7f7f7f7f7f7f7fll;
int u[];
int v[];
int tf[];
int hv[][];
void ade(int f,int t,lnt y)
{
cnt++;
e[cnt].twd=t;
e[cnt].lst=p[f].hd;
p[f].hd=cnt;
e[cnt].tim=y;
}
void dfs(int x,int f)
{
p[x].dp=p[f].dp+;
p[x].fa=f;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to!=f)
{
p[to].val=e[i].tim;
dfs(to,x);
}
}
return ;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++)
{
int a,b;
lnt c;
scanf("%d%d%lld",&a,&b,&c);
ade(a,b,c);
ade(b,a,c);
}
dfs(,);
for(int i=;i<=m;i++)
{
scanf("%d%d",&u[i],&v[i]);
}
if(m==)
{
lnt mtmp=;
lnt mins=;
int x=u[];
int y=v[];
if(p[x].dp<p[y].dp)
swap(x,y);
while(p[x].dp!=p[y].dp)
{
mtmp+=p[x].val;
mins=max(mins,p[x].val);
x=p[x].fa;
}
if(x==y)
{
printf("%lld\n",mtmp-mins);
return ;
}
while(x!=y)
{
mins=max(mins,p[x].val);
mins=max(mins,p[y].val);
mtmp+=p[x].val;
x=p[x].fa;
mtmp+=p[y].val;
y=p[y].fa;
}
printf("%lld\n",mtmp-mins);
return ;
}
for(int i=;i<=m;i++)
{
lnt mtmp=;
int x=u[i];
int y=v[i];
if(p[x].dp<p[y].dp)
swap(x,y);
while(p[x].dp!=p[y].dp)
{
hv[i][x]=;
mtmp+=p[x].val;
x=p[x].fa;
}
if(x==y)
{
tf[i]=mtmp;
continue;
}
while(x!=y)
{
hv[i][x]=;
hv[i][y]=;
mtmp+=p[x].val;
x=p[x].fa;
mtmp+=p[y].val;
y=p[y].fa;
}
tf[i]=mtmp;
}
for(int i=;i<=n;i++)
{
lnt maxs=;
for(int j=;j<=m;j++)
{
maxs=max(maxs,tf[j]-(lnt)hv[j][i]*p[i].val);
}
ans=min(ans,maxs);
}
printf("%lld\n",ans);
return ;
}
正解:
二分答案+树上打差分
将计划排序。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long lnt;
struct pnt{
int fa;
int dp;
int hd;
int ola;
int sgrl;
lnt dis;
}p[];
struct ent{
int twd;
int lst;
lnt vls;
}e[];
struct qnt{
int u;
int v;
lnt dtc;
}q[];
int n,m;
int cnt;
int ont;
int lsd;
int top;
int old[][];
int lg[];
int lns[];
int lfs[];
bool cmp(qnt x,qnt y)
{
return x.dtc>y.dtc;
}
void ade(int f,int t,lnt v)
{
cnt++;
e[cnt].twd=t;
e[cnt].lst=p[f].hd;
e[cnt].vls=v;
p[f].hd=cnt;
}
void dfs_build(int x,int f)
{
old[][++ont]=x;
p[x].fa=f;
p[x].dp=p[f].dp+;
p[x].ola=ont;
bool flag=;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to!=f)
{
flag=false;
p[to].dis=p[x].dis+e[i].vls;
dfs_build(to,x);
old[][++ont]=x;
}
}
if(flag)
{
lfs[++lsd]=x;
}
}
void Tr_dfs(int x,int f)
{
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to!=f)
{
Tr_dfs(to,x);
p[x].sgrl+=p[to].sgrl;
}
}
return ;
}
int rmaxs(int x,int y)
{
return p[x].dp>p[y].dp?y:x;
}
int lca(int x,int y)
{
if(p[x].ola>p[y].ola)
swap(x,y);
int lgg=lg[p[y].ola-p[x].ola+];
return rmaxs(old[lgg][p[x].ola],old[lgg][p[y].ola-(<<lgg)+]);
}
int Ccl(int agc)
{
int x=;
while(agc<q[x+].dtc)x++;
if(lns[x])return lns[x];
for(int i=;i<=n;i++)
p[i].sgrl=;
for(int i=;i<=x;i++)
{
p[q[i].u].sgrl++;
p[q[i].v].sgrl++;
p[lca(q[i].v,q[i].u)].sgrl-=;
}
Tr_dfs(,);
lnt ans=;
for(int i=;i<=n;i++)
{
if(p[i].sgrl==x)
{
ans=max(ans,p[i].dis-p[p[i].fa].dis);
}
}
lns[x]=ans;
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++)
{
int x,y;
int z;
scanf("%d%d%d",&x,&y,&z);
ade(x,y,z);
ade(y,x,z);
}
for(int i=;i<=*n;i++)
{
lg[i]=lg[i/]+;
}
dfs_build(,);
for(int i=;i<=;i++)
for(int j=;j+(<<i)-<=ont;j++)
old[i][j]=rmaxs(old[i-][j],old[i-][j+(<<i-)]);
for(int i=;i<=m;i++)
{
scanf("%d%d",&q[i].u,&q[i].v);
q[i].dtc=p[q[i].u].dis+p[q[i].v].dis-*p[lca(q[i].v,q[i].u)].dis;
}
sort(q+,q+m+,cmp);
int l=;
int r=q[].dtc;
int ans;
while(l<=r)
{
int mid=(l+r)>>;
if(q[].dtc-Ccl(mid)>mid)l=mid+;
else{
ans=mid;
r=mid-;
}
}
printf("%d\n",ans);
return ;
}
NOIP2015运输计划(二分答案)的更多相关文章
- 【bzoj4326】[NOIP2015]运输计划 二分答案+LCA
题目描述 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球.小 P 掌管一家物流公司, 该 ...
- BZOJ 4326 NOIP2015 运输计划 (二分+树上差分)
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1930 Solved: 1231[Submit][Statu ...
- [luogu]P2680 运输计划[二分答案][树上差分]
[luogu]P2680 [NOIP2015]运输计划 题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n ...
- loj2425 「NOIP2015」运输计划[二分答案+树上差分]
看到题意最小化最长路径,显然二分答案,枚举链长度不超过$\text{mid}$,然后尝试检验.````` 检验是否存在这样一个边置为0后,全部链长$\le\text{mid}$,其最终目标就是.要让所 ...
- luogu P2680 运输计划 (二分答案+树上差分)
题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间 ...
- vijos 运输计划 - 二分答案 - 差分 - Tarjan
Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球.小 P 掌管一家 ...
- BZOJ 4326: NOIP2015 运输计划(二分,树上差分)
Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 1945 Solved: 1243[Submit][Status][Discuss] Descript ...
- 运输计划[二分答案 LCA 树上差分]
也许更好的阅读体验 \(\mathcal{Description}\) 原题链接 概括一下题意 给一颗有\(n\)个点带边权的树,有\(m\)个询问,每次询问\(u,v\)两点间的权值和,你可以将树中 ...
- NOIP2015 运输计划 - 二分 + 树链剖分 / (倍增 + 差分)
BZOJ CodeVS Uoj 题目大意: 给一个n个点的边带权树,给定m条链,你可以选择树中的任意一条边,将它置为0,使得最长的链长最短. 题目分析: 最小化最大值,二分. 二分最短长度mid,将图 ...
- cogs2109 [NOIP2015] 运输计划
cogs2109 [NOIP2015] 运输计划 二分答案+树上差分. STO链剖巨佬们我不会(太虚伪了吧 首先二分一个答案,下界为0,上界为max{路径长度}. 然后判断一个答案是否可行,这里用到树 ...
随机推荐
- Eclipse快捷键 10个最实用的快捷键
Eclipse中10个最实用的快捷键组合 一个Eclipse骨灰级开发人员总结了他觉得最实用但又不太为人所知的快捷键组合.通过这些组合能够更加easy的浏览源代码.使得总体的开发效率和质量得到提升. ...
- Lesson 2 Building your first web page: Part 2
Tag Diagram You may have noticed that HTML tags come in pairs; HTML has both an opening tag (<tag ...
- nyoj--20--吝啬的国度(搜索dfs)
吝啬的国度 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 在一个吝啬的国度里有N个城市,这N个城市间只有N-1条路把这个N个城市连接起来.现在,Tom在第S号城市,他有 ...
- POJ 1330 Nearest Common Ancestors 倍增算法的LCA
POJ 1330 Nearest Common Ancestors 题意:最近公共祖先的裸题 思路:LCA和ST我们已经很熟悉了,但是这里的f[i][j]却有相似却又不同的含义.f[i][j]表示i节 ...
- Google Nexus 5x Android 7.0 Root
很久没有写东西了,准备重新养成这个好习惯.因为自己一直在用Nexus,前段时间自己的Nexus5老的不行了,所以买了台5x,一直没时间root,今天有时间终于有时间弄一下. 在这里整理分享一下. 开始 ...
- json.js
由于json官网被强,现保存源码一份以备不时之需,直接保存成js文件即可. /* json.js 2007-08-05 Public Domain This file adds these metho ...
- openSUSE Leap与 SELS的区别
openSUSE Leap 是 openSUSE 常规发行版本的新名称,在 13.2 之前它仅仅被称为“openSUSE”. 一.openSUSE 发行周期:(15年以前仅有一个openSUSE发行版 ...
- Vue总结(一)
vue总结 构建用户界面的渐进式框架 渐进式:用到什么功能即可使用转么的框架子模块. 两个核心点 向应的数据绑定 当时图发生改变->自动跟新视图,利用Object.defindProperty中 ...
- JSP页面的静态包含和动态包含的区别与联系
JSP中有两种包含: 静态包含:<%@include file="被包含页面"%> 动态包含:<jsp:include page="被包含页面" ...
- 昼猫笔记 JavaScript -- 闭包
本次主要内容是 闭包 阅读时间: 约 3分钟 记得点个赞支持支持我哦 初步了解 先看下代码,输出结果是多少? function fn1 () { var a = 2 function fn2 () ...