• 【NOIP 2015 DAY2 T3】 运输计划 (树链剖分-LCA)


    题目背景

    公元 2044 年,人类进入了宇宙纪元。

    题目描述

    L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球。

    小 P 掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物

    流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道 是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之 间不会产生任何干扰。

    为了鼓励科技创新,L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小 P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。

    在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后, 这 m 个运输计划会同时开始,所有飞船一起出发。当这 m 个运输计划都完成时,小 P 的 物流公司的阶段性工作就完成了。

    如果小 P 可以自由选择将哪一条航道改造成虫洞,试求出小 P 的物流公司完成阶段 性工作所需要的最短时间是多少?

    输入输出格式

    输入格式:

    输入文件名为 transport.in。

    第一行包括两个正整数 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的物流公司完成阶段性工作所需要的最短时间。

    输入输出样例

    输入样例#1:
    6 3 
    1 2 3 
    1 6 4 
    3 1 7 
    4 3 6 
    3 5 5 
    3 6 
    2 5 
    4 5
    输出样例#1:
    11

    说明

    所有测试数据的范围和特点如下表所示

    请注意常数因子带来的程序效率上的影响。

    【分析】

      这题,像是很多解法哦。

      首先是,你是选大的那几条链删掉公共边,就是树链的交,然后维护一个最大值【可是我不会树链的交【如果没有交链直接break就好了

      

      我打的是二分版本。  

      先预处理每条路径的LCA,二分答案,如果某条路径的长度大于这个二分答案,那么意味着他里面一定要割掉一条边嘛,

      那么,把这样的路径记录下来(那个,是一个很妙的方法,在x,y上标记1,在lca上标记-2,子树的sum就是它的访问次数,我们判断的时候只需要dfs一遍,回溯累加就好了)

      我们只能选择涵盖所有不合法路径的边减掉,取他们之中的max当然是更好的,然后看看这个max能不能使路径合法。

      【为什么我打的nlogxx比别人的暴力还慢【捂脸= =

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 #include<cmath>
      8 using namespace std;
      9 #define Maxn 300010
     10 #define LL long long
     11 
     12 struct node
     13 {
     14     int x,y,c,next;
     15 }t[Maxn*2];int len;
     16 
     17 int n,m;
     18 
     19 int first[Maxn];
     20 int ax[Maxn],ay[Maxn],lca[Maxn];
     21 LL h[Maxn],ln[Maxn];
     22 
     23 void ins(int x,int y,int c)
     24 {
     25     t[++len].x=x;t[len].y=y;t[len].c=c;
     26     t[len].next=first[x];first[x]=len;
     27 }
     28 
     29 LL mymax(LL x,LL y) {return x>y?x:y;}
     30 
     31 int dep[Maxn],dfn[Maxn],sm[Maxn],son[Maxn];
     32 int fa[Maxn],w[Maxn];
     33 void dfs1(int x,int f)
     34 {
     35     dep[x]=dep[f]+1;sm[x]=1;son[x]=0;
     36     fa[x]=f;
     37     for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
     38     {
     39         int y=t[i].y;
     40         w[y]=t[i].c;
     41         dfs1(y,x);
     42         sm[x]+=sm[y];
     43         if(sm[y]>sm[son[x]]) son[x]=y;
     44     }
     45 }
     46 
     47 int tp[Maxn],cnt=0;
     48 void dfs2(int x,int tpp)
     49 {
     50     dfn[x]=++cnt;h[cnt]=h[cnt-1]+w[x];
     51     tp[x]=tpp;
     52     if(son[x]) dfs2(son[x],tpp);
     53     for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x]&&t[i].y!=son[x])
     54     {
     55         int y=t[i].y;
     56         dfs2(y,y);
     57     }
     58 }
     59 
     60 void ffind(int id,int x,int y)
     61 {
     62     int tt;
     63     while(tp[x]!=tp[y])
     64     {
     65         if(dep[tp[x]]<dep[tp[y]]) tt=x,x=y,y=tt;
     66         ln[id]+=h[dfn[x]]-h[dfn[tp[x]]-1];
     67         x=fa[tp[x]];
     68     }
     69     if(dep[x]<dep[y]) tt=x,x=y,y=tt;
     70     ln[id]+=h[dfn[x]]-h[dfn[y]];
     71     lca[id]=y;
     72 }
     73 
     74 int tot[Maxn];
     75 
     76 int les(int x,int tt)
     77 {
     78     int ans=-1;
     79     for(int i=first[x];i;i=t[i].next) if(t[i].y!=fa[x])
     80     {
     81         int y=t[i].y;
     82         int now=les(y,tt);
     83         tot[x]+=tot[y];
     84         if(now!=-1) ans=mymax(ans,now);
     85     }
     86     if(tot[x]==tt) ans=mymax(ans,w[x]);
     87     return ans;
     88 }
     89 
     90 bool check(LL mid)
     91 {
     92     memset(tot,0,sizeof(tot));
     93     LL mx=0;int tt=0;
     94     for(int i=1;i<=m;i++) if(ln[i]>mid)
     95     {
     96             tot[ax[i]]++;tot[ay[i]]++;
     97             tot[lca[i]]-=2;
     98         mx=mymax(mx,ln[i]);
     99         tt++;
    100     }
    101     int now=les(1,tt);
    102     if(now==-1||mx-now>mid) return 0;
    103     return 1;
    104 }
    105 
    106 void get_ans(LL l,LL r)
    107 {
    108     while(l<r)
    109     {
    110         LL mid=(l+r)/2;
    111         if(check(mid)) r=mid;
    112         else l=mid+1;
    113     }
    114     printf("%lld
    ",l);
    115 }
    116 
    117 int main()
    118 {
    119     LL mx=0;
    120     scanf("%d%d",&n,&m);
    121     len=0;
    122     memset(first,0,sizeof(first));
    123     for(int i=1;i<n;i++)
    124     {
    125         int x,y,c;
    126         scanf("%d%d%d",&x,&y,&c);
    127         ins(x,y,c);ins(y,x,c);
    128     }
    129     dep[0]=0;
    130     dfs1(1,0);h[0]=0;
    131     dfs2(1,1);
    132     for(int i=1;i<=m;i++)
    133     {
    134         scanf("%d%d",&ax[i],&ay[i]);
    135         ffind(i,ax[i],ay[i]);
    136         mx=mymax(mx,ln[i]);
    137     }
    138     get_ans(0,mx);
    139     return 0;
    140 }
    View Code

    2016-11-15 16:41:22

  • 相关阅读:
    xml在html中的使用
    getElementsByTagName的用法
    opener 的使用
    动态增加属性
    innerText, innerHTML,outerHTML
    button的css属性
    动态改变select中option的次序
    input 的样式
    zkw线段树
    接着吐槽(2012/5/23)
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6066297.html
Copyright © 2020-2023  润新知