zoukankan      html  css  js  c++  java
  • [NOIp 2015]运输计划

    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

    第一行包括两个正整数 n、m,表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 1 到 n 编号。

    接下来 n-1 行描述航道的建设情况,其中第 i 行包含三个整数 ai, bi 和 ti,表示第i 条双向航道修建在 ai 与 bi 两个星球之间,任意飞船驶过它所花费的时间为 ti。

    接下来 m 行描述运输计划的情况,其中第 j 行包含两个正整数 uj 和 vj,表示第 j个 运输计划是从 uj 号星球飞往 vj 号星球。

    Output

    输出 共1行,包含1个整数,表示小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

    Sample Explanation

    Hint

    题解

    抓取有用信息:

    1、给定一棵$n$个点的带边权的树,给定$m$条路径;
    2、求将任意一条边的边权置为$0$后所有路径长度最大值的最小值。

    20分算法:

    1、由于是一棵树,所以所有的路径都是最短路径,结合题目给定的数据范围,可以用合适的数据结构解决;
    2、枚举被操作的边,$DFS$统计所有路径长度的最大值,然后更新答案;
    3、时间复杂度$O(n^2*m)$。

    40分算法:

    1、枚举被操作的边,使用树链剖分等树上数据结构统计所有路径长度的最大值,然后更新答案;
    2、时间复杂度$O(n^2log_2n)$。

    60分算法:

    1、先使用各种方法预处理出$LCA$,枚举被操作的边;
    2、$DFS$在$O(n)$时间内统计所有路径的长度的最大值,然后更新答案;
    3、时间复杂度$O(n^2)$。
    如何用$DFS$在$O(n)$时间内统计所有路径的长度的最大值?
    计算每一点到根的路径$dis[i]$,所以:
    $$dist(u,v)=dis[u]+dis[v]-2*dis[LCA(u,v)]$$

    100分算法:

    1、先使用各种方法预处理出$LCA$与路径在未操作前的长度,推荐使用$Trajan$算法;
    2、二分答案,即二分出路径长度的最大值$X$;
    3、将所有长度大于$X$的路径找出来,求出最长的路径长度与$X$的差值$D$;
    4、那么显然被删掉的边,边权$≥D$;然后使用各种方法求出这些路径的并集
    (欧拉$DFS$序列或树上差分序列),看这些边的并集中是否有一条边的边权$≥D$,若有则该$X$可行。
    5、时间复杂度$O(nlog_2n)$。

      1 #include<set>
      2 #include<map>
      3 #include<ctime>
      4 #include<cmath>
      5 #include<queue>
      6 #include<stack>
      7 #include<vector>
      8 #include<cstdio>
      9 #include<string>
     10 #include<cstring>
     11 #include<cstdlib>
     12 #include<iostream>
     13 #include<algorithm>
     14 #define LL long long
     15 #define Max(a,b) ((a)>(b) ? (a):(b))
     16 #define Min(a,b) ((a)<(b) ? (a):(b))
     17 using namespace std;
     18 const int N=300000;
     19 
     20 int n,m,u,v,c,lim;
     21 struct tt
     22 {
     23     int to,cost,next;
     24 }edge[N*2+5];
     25 int path[N+5],top;
     26 void Add(int u,int v,int c);
     27 struct ss
     28 {
     29     int a,b,lca,cost;
     30 }p[N+5];
     31 int fa[N+5][20],dist[N+5],dep[N+5];
     32 void Dfs(int r,int depth);
     33 void ST();
     34 void LCA(int k);
     35 
     36 int vis[N+5],cnt;
     37 bool work(int r);
     38 int judge(int r,int father);
     39 
     40 int main()
     41 {
     42     scanf("%d%d",&n,&m);
     43     lim=log(n)/log(2);
     44     for (int i=1;i<n;i++)
     45     {
     46       scanf("%d%d%d",&u,&v,&c);
     47       Add(u,v,c);
     48       Add(v,u,c);
     49     }
     50     for (int i=1;i<=m;i++) scanf("%d%d",&p[i].a,&p[i].b);
     51     Dfs(1,1);
     52     ST();
     53     int maxlenth=0;
     54     for (int i=1;i<=m;i++)
     55     {
     56       LCA(i);
     57       if (p[i].cost>maxlenth) maxlenth=p[i].cost;
     58     }
     59     int l=0,r=maxlenth,ans=maxlenth;
     60     while (l<=r)
     61     {
     62       int mid=(l+r)>>1;
     63       if (work(mid)) ans=mid,r=mid-1;
     64       else l=mid+1;
     65     }
     66     printf("%d
    ",ans);
     67     return 0;
     68 }
     69 
     70 void Add(int u,int v,int c)
     71 {
     72     edge[++top].to=v;
     73     edge[top].cost=c;
     74     edge[top].next=path[u];
     75     path[u]=top;
     76 }
     77 void Dfs(int r,int depth)
     78 {
     79     dep[r]=depth;
     80     for (int i=path[r];i;i=edge[i].next) if (!dep[edge[i].to])
     81     {
     82       fa[edge[i].to][0]=r;
     83       dist[edge[i].to]=dist[r]+edge[i].cost;
     84       Dfs(edge[i].to,depth+1);
     85     }
     86 }
     87 void ST()
     88 {
     89     for (int t=1;t<=lim;t++)
     90       for (int i=1;i<=n;i++)
     91           fa[i][t]=fa[fa[i][t-1]][t-1];
     92 }
     93 void LCA(int k)
     94 {
     95     int a=p[k].a,b=p[k].b;
     96     if (dep[a]<dep[b]) swap(a,b);
     97     for (int i=lim;i>=0;i--) if (dep[fa[a][i]]>=dep[b]) a=fa[a][i];
     98     if (a!=b)
     99     {
    100       for (int i=lim;i>=0;i--) if (fa[a][i]!=fa[b][i]) a=fa[a][i],b=fa[b][i];
    101       a=fa[a][0],b=fa[b][0];
    102     }
    103     p[k].lca=a;
    104     p[k].cost=dist[p[k].a]+dist[p[k].b]-2*dist[p[k].lca];
    105 }
    106 bool work(int r)
    107 {
    108     memset(vis,0,sizeof(vis));
    109     cnt=0;
    110     int maxlenth=0;
    111     for (int i=1;i<=m;i++)
    112       if (p[i].cost>r)
    113       {
    114           cnt++,maxlenth=Max(maxlenth,p[i].cost);
    115           vis[p[i].a]++,vis[p[i].b]++,vis[p[i].lca]-=2;
    116       }
    117     int delta=maxlenth-r;
    118     maxlenth=judge(1,0);
    119     return maxlenth>=delta;
    120 }
    121 int judge(int r,int father)
    122 {
    123     int ans=0;
    124     for (int i=path[r];i;i=edge[i].next) if (edge[i].to!=father)
    125     {
    126       int tmp=judge(edge[i].to,r);
    127       ans=Max(ans,tmp);
    128       vis[r]+=vis[edge[i].to];
    129     }
    130     if (vis[r]==cnt) ans=Max(ans,dist[r]-dist[fa[r][0]]);
    131     return ans;
    132 }
  • 相关阅读:
    Linnia学习记录
    漫漫考研路
    ENS的学习记录
    KnockoutJS 3.X API 第四章 数据绑定(4) 控制流with绑定
    KnockoutJS 3.X API 第四章 数据绑定(3) 控制流if绑定和ifnot绑定
    KnockoutJS 3.X API 第四章 数据绑定(2) 控制流foreach绑定
    KnockoutJS 3.X API 第四章 数据绑定(1) 文本及样式绑定
    KnockoutJS 3.X API 第三章 计算监控属性(5) 参考手册
    KnockoutJS 3.X API 第三章 计算监控属性(4)Pure computed observables
    KnockoutJS 3.X API 第三章 计算监控属性(3) KO如何实现依赖追踪
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7445989.html
Copyright © 2011-2022 走看看