4632 NOIP[2015] 运输计划

时间:2022-01-19 12:07:17

4632 NOIP[2015] 运输计划

 时间限制: 1 s
 空间限制: 256000 KB
 题目等级 : 大师 Master
 
 
 
题目描述 Description

公元 2044 年,人类进入了宇宙纪元。L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球。小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之间不会产生任何干扰。为了鼓励科技创新, L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后,这 m 个运输计划会同时开始,所有飞船一起出发。当这 m 个运输计划都完成时,小 P 的物流公司的阶段性工作就完成了。如果小 P 可以*选择将哪一条航道改造成虫洞, 试求出小 P 的物流公司完成阶段性工作所需要的最短时间是多少?

输入描述 Input Description

第一行包括两个正整数 n,m,表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 1 到 n 编号。接下来 n−1 行描述航道的建设情况,其中第 i 行包含三个整数 ai,bi 和 ti,表示第 i 条双向航道修建在 ai 与 bi 两个星球之间,任意飞船驶过它所花费的时间为 ti。数据保证 1<=ai,bi<=n 且 0<=ti<=1000。接下来 m 行描述运输计划的情况,其中第 j 行包含两个正整数 uj 和 vj,表示第 j 个运输计划是从 uj 号星球飞往 vj号星球。数据保证 1<=ui,vi<=n

输出描述 Output Description

输出文件只包含一个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间。

样例输入 Sample Input

6 3
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5

样例输出 Sample Output

11

数据范围及提示 Data Size & Hint

样例解释:

将第 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= 约定
1 100 1  
2 100 100 第i条航道连接i号星球与i+1号星球
3 100 100  
4 2000 1
5 1000 1000 第i条航道连接i号星球与i+1号星球
6 2000 2000 第i条航道连接i号星球与i+1号星球
7 3000 3000 第i条航道连接i号星球与i+1号星球
8 1000 1000  
9 2000 2000
10 3000 3000
11 80000 1
12 100000 1
13 70000 70000

第i条航道连接i号星球与i+1号星球

14 80000 80000 第i条航道连接i号星球与i+1号星球
15 90000 90000 第i条航道连接i号星球与i+1号星球
16 100000 100000 第i条航道连接i号星球与i+1号星球
17 80000 80000  
18 90000 90000
19 100000 100000
20 300000 300000

所有数据

    1<=ai,bi,uj,vj<=n,0<=ti<=1000

(所有测试点编号加10)

分类标签 Tags 点此展开

 
暂无标签

95分题解:

LCA倍增+二分 只能95分了,最后一个点卡常数,T掉了

先LCA一遍,记下每个任务的起点,终点,公共祖先,所需时间(路程)

对于每个ans 统计>他的路径条数 cnt 并维护最大差值 dec

并且对于每条不合法的路径维护每个点的经过次数

然后枚举点 如果经过次数==cnt说明每一条不合法的都经过他

然后尝试把它建成虫洞 如果他对应边的权值>=dec 那么我们删掉它ans就合法了

统计不满足答案的任务cnt,然后维护一个sum[i]

关键是统计每个点在非法路径中的经过次数 :

维护sum数组 对于每个非法的路径起点a 终点b LCA(a,b)==s sum[a]++ sum[b]++ sum[s]-=2

这样往上更新的话 经过的点的sum值都变成1 祖先s的变成0

并将它们的sum值传到父亲结点,最后看是否能找出某个点i,使sum[i]=tot并且

连到这个点的边权值>= 最大任务时间-答案(即最大差值 dec),如果能,这个答案即为可行答案。

95分+5分(打表)=100分 代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 300010
inline const int read(){
register int x=,f=;
register char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,m,tot;
struct ss{
int a,b,anc,di;
}lca[N];
struct node{
int v,t,next;
}e[N<<];
int b[N],head[N];
int dep[N],dis[N],f[N][];
int l,r,mid,ans,sum[N];
void add(int x,int y,int z){
e[++tot].v=y;
e[tot].t=z;
e[tot].next=head[x];
head[x]=tot;
}
void dfs(int x,int from,int de,int l){
dep[x]=de;
dis[x]=l;
f[x][]=from;
for(int i=head[x];i;i=e[i].next){
if(e[i].v!=from){
b[e[i].v]=i;//与该点相连的边 给其编号
dfs(e[i].v,x,de+,l+e[i].t);
}
}
}
int calc_lca(int a,int b){
if(dep[a]<dep[b]) swap(a,b);
int t=dep[a]-dep[b];
for(int i=;i<=;i++){
if((<<i)&t){
a=f[a][i];
}
}
if(a==b) return a;
for(int i=;i>=;i--){
if(f[a][i]!=f[b][i]){
a=f[a][i];
b=f[b][i];
}
}
return f[a][];
}
void updata(int now,int from){//利用反栈,更新一下sum[]
for(int i=head[now];i;i=e[i].next){
if(e[i].v!=from){
updata(e[i].v,now);
sum[now]+=sum[e[i].v];
}
}
}
bool check(int x){
int cnt=,dec=;//
memset(sum,,sizeof sum);
for(int i=;i<=n;i++){
if(lca[i].di>x){
cnt++;
sum[lca[i].a]++;
sum[lca[i].b]++;
sum[lca[i].anc]-=;
dec=max(dec,lca[i].di-x);
}
}
updata(,);
for(int i=;i<=n;i++) if(sum[i]==cnt&&e[b[i]].t>=dec) return ;
return ;
}
int main(){
n=read();m=read();
if(n==&&m==){puts("");return ;}//point 20 listed
for(int i=,x,y,z;i<n;i++){
x=read();y=read();z=read();
add(x,y,z);add(y,x,z);
}
dfs(,,,);
for(int j=;j<=;j++){
for(int i=;i<=n;i++){
f[i][j]=f[f[i][j-]][j-];
}
}
for(int i=;i<=m;i++){
lca[i].a=read();
lca[i].b=read();
lca[i].anc=calc_lca(lca[i].a,lca[i].b);
lca[i].di=dis[lca[i].a]+dis[lca[i].b]-(dis[lca[i].anc]<<);
r=max(r,lca[i].di);
}
r++;
while(l<r){
mid=(l+r>>);
if(check(mid)) ans=r=mid;
else l=mid+;
}
printf("%d\n",ans);
return ;
}

4632 NOIP[2015] 运输计划

二分+树链剖分求LCA(避免卡常)+差分

AC代码:

2017-04-06

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=3e5+,M=N<<;
int n,m,Q,cnt,ans,maxcost,sum[N],siz[N],son[N],dis[N],top[N],id[N],dep[N],fa[N];
struct data{int s,t,lca,dis;}d[N];
struct edge{int v,w,next;}e[M];int tot,head[N];
inline int read(){
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void add(int x,int y,int z){
e[++tot].v=y;e[tot].w=z;e[tot].next=head[x];head[x]=tot;
e[++tot].v=x;e[tot].w=z;e[tot].next=head[y];head[y]=tot;
}
void dfs(int x,int f,int de,int l){
fa[x]=f;dep[x]=de;dis[x]=l;siz[x]=;
for(int i=head[x];i;i=e[i].next){
if(e[i].v!=f){
dfs(e[i].v,x,de+,l+e[i].w);
siz[x]+=siz[e[i].v];
if(siz[son[x]]<siz[e[i].v]) son[x]=e[i].v;
}
}
}
void getpos(int x,int tp){
top[x]=tp;
id[++cnt]=x;
if(!son[x]) return ;
getpos(son[x],tp);
for(int i=head[x];i;i=e[i].next){
if(e[i].v!=fa[x]&&e[i].v!=son[x]){
getpos(e[i].v,e[i].v);
}
}
}
int lca(int x,int y){
for(;top[x]!=top[y];x=fa[top[x]]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
}
return dep[x]<dep[y]?x:y;
}
bool check(int ans){
int cnt=;
memset(sum,,n+<<);
for(int i=;i<=m;i++){
if(d[i].dis>ans){
++cnt;
sum[d[i].s]++;
sum[d[i].t]++;
sum[d[i].lca]-=;
}
}
for(int i=n;i;i--) sum[fa[id[i]]]+=sum[id[i]];
int dec=maxcost-ans;
for(int i=;i<=n;i++) if(sum[i]==cnt&&dis[i]-dis[fa[i]]>=dec) return ;
return ;
}
int main(){
n=read();m=read();
for(int i=,x,y,z;i<n;i++){
x=read();y=read();z=read();
add(x,y,z);
}
dfs(,,,);getpos(,);
for(int i=;i<=m;i++){
d[i].s=read();
d[i].t=read();
d[i].lca=lca(d[i].s,d[i].t);
d[i].dis=dis[d[i].s]+dis[d[i].t]-(dis[d[i].lca]<<);
maxcost=max(maxcost,d[i].dis);
}
int l=,r=maxcost,mid;
while(l<=r){
mid=l+r>>;
if(check(mid)) r=mid-,ans=mid;
else l=mid+;
}
printf("%d\n",ans);
return ;
}
#include<cstdio>
#include<cstring>
#include<iostream>
#define R register
using namespace std;
int read(){
R int x=;bool f=;
R char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=;ch=getchar();}
while(ch>=''&&ch<=''){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return f?x:-x;
}
const int N=3e5+;
struct node{
int v,dis,next;
}e[N<<];int tot,cnt;
int n,m,head[N];
int dep[N],top[N],siz[N],son[N],fa[N];
int id[N],num[N],val[N],dis[N],dist[N];
int maxcost,from[N],to[N];
void add(int x,int y,int z){
e[++tot]=(node){y,z,head[x]};
head[x]=tot;
}
void dfs(int x,int f,int de,int l){
fa[x]=f;dep[x]=de;dis[x]=dis[f]+l;dist[x]=l;siz[x]=;
for(int i=head[x];i;i=e[i].next){
int v=e[i].v,w=e[i].dis;
if(v!=f){
dfs(v,x,de+,w);
siz[x]+=siz[v];
if(!son[x]||siz[son[x]]<siz[v]) son[x]=v;
}
}
}
void getpos(int x,bool hson){
if(hson) top[x]=top[fa[x]];
else top[x]=x;
id[x]=++cnt;
if(son[x]) getpos(son[x],);
for(int i=head[x];i;i=e[i].next){
int v=e[i].v;
if(v!=fa[x]&&v!=son[x]){
getpos(v,);
}
}
}
int lca(int x,int y){
for(;top[x]!=top[y];x=fa[top[x]]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
}
if(dep[x]>dep[y]) return y;
else return x;
}
void updata(int x,int y){
int ans=;
for(;top[x]!=top[y];x=fa[top[x]]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
if(id[top[x]]<=id[x]) num[id[top[x]]]++,num[id[x]+]--;
}
if(dep[x]>dep[y]) swap(x,y);
if(id[son[x]]<=id[y]) num[id[son[x]]]++,num[id[y]+]--;
}
bool check(int mid){
memset(num,,sizeof num);
int cou=;
for(int i=;i<=m;i++){
if(val[i]>mid){
cou++;
updata(from[i],to[i]);
}
}
if(!cou) return ;
for(int i=;i<=n;i++) num[i]+=num[i-];
for(int i=;i<=n;i++) if(num[id[i]]==cou){
if(maxcost-dist[i]<=mid) return ;
}
return ;
}
int l,r,mid,ans;
int main(){
n=read();m=read();
for(int i=,x,y,z;i<n;i++){
x=read(),y=read(),z=read();
add(x,y,z),add(y,x,z);
}
dfs(,,,);
getpos(,);
for(int i=;i<=m;i++){
from[i]=read();
to[i]=read();
val[i]=dis[from[i]]+dis[to[i]]-*dis[lca(from[i],to[i])];
maxcost=max(maxcost,val[i]);
}
l=;r=maxcost;
while(l<=r){
mid=l+r>>;
if(check(mid)) r=mid-,ans=mid;
else l=mid+;
}
printf("%d\n",ans);
return ;
}

4632 NOIP[2015] 运输计划的更多相关文章

  1. &lbrack;NOIP 2015&rsqb;运输计划-&lbrack;树上差分&plus;二分答案&rsqb;-解题报告

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

  2. Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分)

    Luogu 2680 NOIP 2015 运输计划(树链剖分,LCA,树状数组,树的重心,二分,差分) Description L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之 ...

  3. cogs 2109&period; &lbrack;NOIP 2015&rsqb; 运输计划 提高组Day2T3 树链剖分求LCA 二分答案 差分

    2109. [NOIP 2015] 运输计划 ★★★☆   输入文件:transport.in   输出文件:transport.out   简单对比时间限制:3 s   内存限制:256 MB [题 ...

  4. NOIP&lbrack;2015&rsqb; 运输计划(codevs 4632)

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

  5. NOIP&lbrack;2015&rsqb; 运输计划

    传送门 题目描述 Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球 ...

  6. &lbrack;noip 2015&rsqb;运输计划 &lbrack;LCA&rsqb;&lbrack;树链剖分&rsqb;

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

  7. NOIP 2015运输计划

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

  8. noip 2015 运输计划 (lca&plus;二分)

    /* 95 最后一个点T了 qian lv ji qiong 了 没学过树剖 听chx听xzc说的神奇的方法 Orz 首先求出每个计划的路径长度 这里写的倍增 然后二分答案 对于每个ans 统计&gt ...

  9. 题解——洛谷 P2680 NOIP提高组 2015 运输计划

    树上差分加上二分答案 详细题解待填坑 #include <cstdio> #include <algorithm> #include <cstring> using ...

随机推荐

  1. 如何在openresty里解析域名

    转:原文:http://hambut.com/2016/09/09/how-to-resolve-the-domain-name-in-openresty/?utm_source=tuicool&am ...

  2. new一个数组,delete释放内存

    int *a = new int[4]; for(int i=0;i<4;i++) { a[i] = i; printf("a[%d]=%d\n", i, i); } del ...

  3. SpringMvc入门二----HelloWorld

    1. 导入需要的架包: 2. 配置web.xml,添加Servlet <servlet> <servlet-name>springmvc</servlet-name&gt ...

  4. 获取资源ID

    比如,设置一张gif图片的宽高 gif.setShowDimension((int) CommonUtil.getDimen(R.dimen.gif), (int) CommonUtil.getDim ...

  5. C语言编程的进制问题问题

    在我们的编译器,我用的是ADS   开发平台,现在RTC模块编程时,2410作为上位机,如下代码: n = rBCDDATE;if(n==1) time->day =0x31 ; 波斯历的日期与 ...

  6. 【编程范式】汇编解释swap方法

    先要熟悉一些汇编的基本知识: 1.SP是什么? SP是堆栈寄存器,在调用子程序时,都会用到,保存原来程序的环境使用,如各个寄存器的内容,最重要的是,调用返回时程序的运行指令地址,这是由调用时将返回地址 ...

  7. 改变HTML中超链接的显示样式

    更详细的内容请参考:http://www.w3school.com.cn/tags/tag_a.asp HTML中的代码如下: <a class="news_title" t ...

  8. 【SSM之旅】Spring&plus;SpringMVC&plus;MyBatis&plus;Bootstrap整合基础篇(一)项目简介及技术选型相关介绍

    试水 一直想去搭建个自己的个人博客,苦于自己的技术有限,然后也个人也比较懒散.想动而不能动,想动而懒得动,就这么一直拖到了现在.总觉得应该把这几年来的所学总结一番,这样才能有所成长. 不知在何时,那就 ...

  9. Markdown对应Yelee主题语法

    概述 这里说的是Yelee主题的语法和原生语法是有些区别的:更多的基础语法可以到Cmd Markdown上面去查看:但是我觉得都会各有不同吧 注意这里说的不是真正意义上的Markdown语法 标题 一 ...

  10. ZeptoLab Code Rush 2015 B&period; Om Nom and Dark Park DFS

    B. Om Nom and Dark Park Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/5 ...