UOJ150 运输计划

运输计划
(transport.cpp/c/pas)
【问题描述】
公元 2044 年,人类进入了宇宙纪元。L 国有 n 个星球,还有 n-1 条 双向 航道,每条航道建立在两个星球之间,这 n-1 条航道 连通 了 L 国的所有星球。
小 P 掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 u i 号星球沿 最快 的宇航路径飞行到 v i 号星球去。显然,飞船驶过一条航道是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 t j ,并且任意两艘飞船之间 不会 产生任何干扰。
为了鼓励科技创新,L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小P 把某一条航道改造成虫洞,飞船驶过虫洞 不消耗 时间。在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后,这 m 个运输计划会 同时 开始,所有飞船 一起 出发。当这 m 个运输计划 都完成 时,小 P 的物流公司的阶段性工作就完成了。如果小 P 可以 自由选择 将哪一条航道改造成虫洞,试求出小 P 的物流公司完成阶段性工作所需要的最短时间是多少?
【输入格式】
输入文件名为 transport.in。
第一行包括两个正整数 n、 m,表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 1 到 n 编号。
接下来 n-1 行描述航道的建设情况,其中第 i 行包含三个整数 a i , b i 和 t i ,表示第i 条双向航道修建在 a i 与 b i 两个星球之间,任意飞船驶过它所花费的时间为 t i 。
接下来 m 行描述运输计划的情况,其中第 j 行包含两个正整数 u j 和 v j ,表示第 j 个运输计划是从 u j 号星球飞往 v j 号星球。
【输出格式】
输出文件名为 transport.out。
共 1 行,包含 1 个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间。

正解:树链剖分+二分答案+差分

解题报告:

  NOIP2015的原题,还记得这道题当年的考场上打的是倍增的暴力。。。

  首先链剖,并预处理一下每个计划的原始距离。二分一个答案x,找出所有距离大于x的计划,单独处理。显然我们需要使这些计划的总时间都要变少,那么我们必须要找出一条边被这所有的超时的计划所包含,并尽可能的使这条边的权值大,这样的话,我们可以考虑把边被经过的次数差分,所有计划求lca的时候顺便差分一下,标记一下经过的边。最后一遍统计每条边的经过次数,如果刚好等于超时的计划,我们才考虑这条边是否可以产生贡献,如果至少有一个计划不满足,无论如何不可能。最后只需要比较一下这条边能否使时间最大的计划完成即可完成可行性判断。

  代码如下:

  1 //It is made by jump~
  2 #include <iostream>
  3 #include <cstring>
  4 #include <cstdio>
  5 #include <algorithm>
  6 #include <ctime>
  7 using namespace std;
  8 typedef long long LL;
  9 #define RG register
 10 const int MAXN = 300011;
 11 const int MAXM = 300011;
 12 int n,m,ecnt,Max,ans,cnt;
 13 int first[MAXN],to[MAXN*2],next[MAXN*2],w[MAXN*2];
 14 int deep[MAXN],top[MAXN],size[MAXN],son[MAXN],father[MAXN],id[MAXN],sum[MAXN],quan[MAXN];
 15 int b[MAXN];//差分数组,统计经过某条边的次数
 16 int l,r,root;
 17 struct fight{
 18     int u,v;
 19     int dis;
 20 }a[MAXM];
 21
 22 inline int getint()
 23 {
 24        RG int w=0,q=0; char c=getchar();
 25        while((c<‘0‘ || c>‘9‘) && c!=‘-‘) c=getchar(); if(c==‘-‘) q=1,c=getchar();
 26        while (c>=‘0‘ && c<=‘9‘) w=w*10+c-‘0‘, c=getchar(); return q ? -w : w;
 27 }
 28
 29 inline void dfs(RG int x,RG int fa){
 30     size[x]=1;
 31     for(RG int i=first[x];i;i=next[i]) {
 32     RG int v=to[i]; if(v==fa) continue;
 33     quan[v]=w[i];
 34     deep[v]=deep[x]+1; father[v]=x; dfs(v,x); size[x]+=size[v];
 35     if(size[v]>=size[son[x]]) son[x]=v;
 36     }
 37 }
 38
 39 inline void dfs2(RG int x,RG int fa){
 40     id[x]=++ecnt; sum[ecnt]=sum[ecnt-1]+quan[x];
 41     if(son[x]) top[son[x]]=top[x],dfs2(son[x],x);
 42     for(RG int i=first[x];i;i=next[i]) {
 43     RG int v=to[i]; if(v==fa || v==son[x]) continue;
 44     top[v]=v; dfs2(v,x);
 45     }
 46 }
 47
 48 inline void lca(RG int now){
 49     RG int x=a[now].u,y=a[now].v;
 50     RG int f1=top[x],f2=top[y];
 51     while(f1!=f2) {
 52     if(deep[f1]<deep[f2]) swap(f1,f2),swap(x,y);
 53     a[now].dis+=sum[id[x]]-sum[id[f1]-1];
 54     x=father[f1]; f1=top[x];
 55     }
 56     if(deep[x]<deep[y]) swap(x,y);
 57     a[now].dis+=sum[id[x]]-sum[id[son[y]]-1];//应该是son[y],因为到y为止是y连了y在内的
 58 }
 59
 60 inline void update(RG int now){
 61     RG int x=a[now].u,y=a[now].v;
 62     RG int f1=top[x],f2=top[y];
 63     while(f1!=f2) {
 64     if(deep[f1]<deep[f2]) swap(f1,f2),swap(x,y);
 65     b[id[f1]]++; b[id[x]+1]--;
 66     x=father[f1]; f1=top[x];
 67     }
 68     if(deep[x]<deep[y]) swap(x,y);
 69     b[id[son[y]]]++; b[id[x]+1]--;//+1
 70 }
 71
 72 inline bool check(RG int x){
 73     cnt=0;//统计不能在规定时间内完成的
 74     memset(b,0,sizeof(b));
 75     RG int cost=0;
 76     for(RG int i=1;i<=n;i++) {
 77     if(a[i].dis>x) {
 78         cnt++; cost=max(cost,a[i].dis-x);
 79         update(i);
 80     }
 81     }
 82     RG int zuida=0,now=0;
 83     for(RG int i=1;i<=n;i++) {//讨论的是结点编号,而不是结点本身!
 84     now+=b[i];
 85     if(now==cnt) {//必须是覆盖了所有,否则的话就没有用
 86         zuida=max(sum[i]-sum[i-1],zuida);
 87     }
 88     }
 89     if(zuida>=cost) return true;
 90     return false;
 91 }
 92
 93 inline void work(){
 94     //srand(time(NULL));
 95     n=getint(); m=getint(); RG int x,y,z;
 96     for(RG int i=1;i<n;i++) {
 97     x=getint(); y=getint(); z=getint(); Max+=z;
 98     next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; w[ecnt]=z;
 99     next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x; w[ecnt]=z;
100     }
101     //root=rand()%n+1;
102     root=n/2;
103     deep[root]=1; dfs(root,0);
104     ecnt=0; top[root]=root; dfs2(root,0);
105
106     RG int mid;
107     for(RG int i=1;i<=m;i++) a[i].u=getint(),a[i].v=getint(),lca(i);
108     l=0; r=Max;
109     ans=0;
110     while(l<=r) {
111     mid=(l+r)/2;
112     if(check(mid)) ans=mid,r=mid-1;
113     else l=mid+1;
114     }
115     printf("%d",ans);
116 }
117
118 int main()
119 {
120   work();
121   return 0;
122 }
时间: 2024-11-17 15:34:07

UOJ150 运输计划的相关文章

树链剖分-Hello!链剖-[NOIP2015]运输计划-[填坑]

This article is made by Jason-Cow.Welcome to reprint.But please post the writer's address. http://www.cnblogs.com/JasonCow/ [NOIP2015]运输计划    Hello!链剖.你好吗? 题意: 给出一棵n个节点的带权树,m对树上点对 现在允许删除一条边,(权值修改为0) 输出: 最小化的点对间最大距离 1.链剖 2.树上差分 3.二分 链剖我就不多说了,就是两dfs 注意

[NOIP2015] 提高组 洛谷P2680 运输计划

题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物 流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去.显然,飞船驶过一条航道 是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之 间不会产生任何干扰. 为了鼓励科技创新,L 国国王同意小 P 的

[BZOJ4326][codevs4632][codevs5440][UOJ#150][NOIP2015]运输计划

试题描述 公元 2044 年,人类进入了宇宙纪元. L 国有 n 个星球,还有 n?1 条双向航道,每条航道建立在两个星球之间,这 n?1 条航道连通了 L 国的所有星球. 小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去.显然,飞船驶过一条航道是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之间不会产生任何干扰. 为了鼓励科技创新, L 国国王同意小 P 的物流公司参与

Vijos[1983]NOIP2015Day2T3 运输计划 transport LCA

题目链接Vijos 题目链接UOJ 转载一个大佬的题解: 点击这里->银牌爷题解 主要考察二分查找.树上倍增.贪心."树上前缀和".题目是一颗树,要求将一条边的权值变为0,使得所有运输计划的最大时间最小.直觉告诉我们,这是一个树上倍增的题目,但是它却不像前几年的 Day2T3 开车旅行那样纯倍增,或许更像疫情控制一些,倍增只是辅助算法,还需要配合其他算法.由于要使所有运输计划的最大时间最小,不难想到二分答案的方法.使C(t)表示是否可以改造一条边,使得改造之后所有运输计划中最长的

NOIp 2015 运输计划

运输计划 问题大意 有n个星球与n-1条双向边,每条边有时间ti,有m个从vi到ui的运输计划.允许你将一条边的时间降为0.同时开始所有的计划,问最小要多少时间完成计划. 输入输出格式 输入格式: 输入文件名为 transport.in. 第一行包括两个正整数 n.m,表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 1 到 n 编号. 接下来 n-1 行描述航道的建设情况,其中第 i 行包含三个整数 ai, bi 和 ti,表示第 i 条双向航道修建在 ai 与 bi 两个星

运输计划

版权声明:本文为博主原创文章,未经博主允许不得转载. 传送门:运输计划 题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球. 小 P 掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物 流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去.显然,飞船驶过一条航道 是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘

BZOJ 4326:NOIP2015 运输计划(二分+差分+lca)

NOIP2015 运输计划Description公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球.小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去.显然,飞船驶过一条航道是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之间不会产生任何干扰.为了鼓励科技创新, L

NOIP2015 运输计划(二分+LCA+差分)

4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 308  Solved: 208[Submit][Status][Discuss] Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n−1 条双向航道,每条航道建立在两个星球之间,这 n−1 条航道连通了 L 国的所有星球.小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui

bzoj4326 运输计划

4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MB Description 公元 2044 年,人类进入了宇宙纪元.L 国有 n 个星球,还有 n?1 条双向航道,每条航道建立在两个星球之间,这 n?1 条航道连通了 L 国的所有星球.小 P 掌管一家物流公司, 该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去.显然,飞船驶过一条航道是需要时间的,对于航道 j,