zoukankan      html  css  js  c++  java
  • noip2015 运输计划

    https://www.luogu.org/problemnew/show/P2680

    首先预处理出每个计划的原时间,然后把计划按时间从小到大排序

    显然,最优方案一定是选某一个计划i,记路径集合S为i以及排序后在i后面的所有计划的路径,找出S中所有路径的交集(如果交集为空则无答案),取交集中所有边上长度的最大值(交集显然一定也是一条可以只用两个端点来表示的路径),这样对于S中所有路径,都可以去掉这条边,因此此时答案为max(最长一条路径所需时间-这个最大值,排序后的第i-1条路径所需时间)

    因此如果能求路径交集,那么只要按时间从大到小扫一遍即可

    然后我不会求路径交。。。

    搜了一下,有两种,第一种是暴力求出要求路径交的两个点对(a,b)与(c,d)共4个点之间的6对lca,显然路径交的两个端点都在这6个点中,那么枚举两个端点(x,y)然后取合法(就是满足x,y都分别在(a,b)路径上与(c,d)路径上)且(x,y)间距离最长的作为答案即可

    然后超大常数、超大代码量、超大调试量、超丑代码等着我。。。。

    (好像还有一种是把每条路径拆成深度单调的两条,对于四条路径两两求交,然后并起来?更麻烦的样子啊)

    曾经错误:

    1.22行maxn[u][i]=max(maxn[u][i-1],maxn[anc[i][i-1]][i-1]);

    2.58行max(ans,maxn[a][0])【老错误了】

    3.85行的||打成&&

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<vector>
      4 #define pb push_back
      5 #define fi first
      6 #define se second
      7 using namespace std;
      8 struct E
      9 {
     10     int to,nxt,d;
     11 }e[600100];
     12 int f1[300100],ne,anc[300100][30],l2n=19,dep[300100],dd[300100];
     13 int maxn[300100][30];
     14 int n,m;
     15 int lft[40];
     16 void dfs1(int u,int fa)
     17 {
     18     int i,k;
     19     for(i=1;i<=l2n;i++)
     20     {
     21         anc[u][i]=anc[anc[u][i-1]][i-1];
     22         maxn[u][i]=max(maxn[u][i-1],maxn[anc[u][i-1]][i-1]);
     23     }
     24     for(k=f1[u];k;k=e[k].nxt)
     25         if(e[k].to!=fa)
     26         {
     27             dep[e[k].to]=dep[u]+1;
     28             dd[e[k].to]=dd[u]+e[k].d;
     29             anc[e[k].to][0]=u;
     30             maxn[e[k].to][0]=e[k].d;
     31             dfs1(e[k].to,u);
     32         }
     33 }
     34 int lca(int a,int b)
     35 {
     36     if(dep[a]<dep[b])    swap(a,b);
     37     int i,t=dep[a]-dep[b];
     38     for(i=l2n;i>=0;i--)
     39         if(lft[i]<=t)
     40             a=anc[a][i],t-=lft[i];
     41     if(a==b)    return a;
     42     for(i=l2n;i>=0;i--)
     43         if(anc[a][i]!=anc[b][i])
     44             a=anc[a][i],b=anc[b][i];
     45     return anc[a][0];
     46 }
     47 int getmax(int a,int b)
     48 {
     49     if(dep[a]<dep[b])    swap(a,b);
     50     int i,t=dep[a]-dep[b],ans=0;
     51     for(i=l2n;i>=0;i--)
     52         if(lft[i]<=t)
     53             ans=max(ans,maxn[a][i]),a=anc[a][i],t-=lft[i];
     54     if(a==b)    return ans;
     55     for(i=l2n;i>=0;i--)
     56         if(anc[a][i]!=anc[b][i])
     57             ans=max(ans,maxn[a][i]),ans=max(ans,maxn[b][i]),a=anc[a][i],b=anc[b][i];
     58     return max(ans,max(maxn[a][0],maxn[b][0]));
     59 }
     60 int getdis(int a,int b)
     61 {
     62     return dd[a]+dd[b]-2*dd[lca(a,b)];
     63 }
     64 struct Q
     65 {
     66     int a,b,d;
     67 }q[300100];
     68 bool operator<(const Q &a,const Q &b)    {return a.d<b.d;}
     69 int k_anc(int a,int k)//a的k级祖先
     70 {
     71     int i;
     72     for(i=l2n;i>=0;i--)
     73         if(lft[i]<=k)
     74             a=anc[a][i],k-=lft[i];
     75     return a;
     76 }
     77 bool isanc(int a,int b)//b是否是a或a的祖先
     78 {
     79     if(dep[b]>dep[a])    return 0;
     80     return k_anc(a,dep[a]-dep[b])==b;
     81 }
     82 typedef pair<int,int> P;
     83 bool isin(int a,const P &b)//点a是否在点对b间路径上
     84 {
     85     return (isanc(b.fi,a)||isanc(b.se,a))&&!isanc(anc[lca(b.fi,b.se)][0],a);
     86 }
     87 bool isin(const P &a,const P &b)//点对a间路径是否被包含在点对b间路径中
     88 {
     89     return isin(a.fi,b)&&isin(a.se,b);
     90 }
     91 P get(const P &a,const P &b)
     92 {
     93     int tmp[]={
     94         lca(a.fi,a.se),lca(a.fi,b.fi),lca(a.fi,b.se),
     95         lca(a.se,b.fi),lca(a.se,b.se),lca(b.fi,b.se),
     96     };
     97     bool ok=0;int i,j,dd,dt;P t,ans(0,0);
     98     for(i=0;i<6;i++)
     99         for(j=i+1;j<6;j++)
    100         {
    101             t=P(tmp[i],tmp[j]);
    102             if(isin(t,a)&&isin(t,b))
    103             {
    104                 if(!ok)
    105                 {
    106                     ok=1;ans=t;
    107                     dd=dep[t.fi]+dep[t.se]-2*dep[lca(t.fi,t.se)]+1;
    108                 }
    109                 else
    110                 {
    111                     dt=dep[t.fi]+dep[t.se]-2*dep[lca(t.fi,t.se)]+1;
    112                     if(dt>dd)    dd=dt,ans=t;
    113                 }
    114             }
    115         }
    116     return ans;
    117 }
    118 int anss;
    119 int main()
    120 {
    121     int i,a,b,d;lft[0]=1;
    122     for(i=1;i<=l2n;i++)    lft[i]=lft[i-1]<<1;
    123     scanf("%d%d",&n,&m);
    124     for(i=1;i<n;i++)
    125     {
    126         scanf("%d%d%d",&a,&b,&d);
    127         e[++ne].to=b;e[ne].nxt=f1[a];f1[a]=ne;e[ne].d=d;
    128         e[++ne].to=a;e[ne].nxt=f1[b];f1[b]=ne;e[ne].d=d;
    129     }
    130     dfs1(1,0);
    131     for(i=1;i<=m;i++)
    132     {
    133         scanf("%d%d",&q[i].a,&q[i].b);
    134         q[i].d=getdis(q[i].a,q[i].b);
    135     }
    136     sort(q+1,q+m+1);
    137     //printf("a%d
    ",getmax(3,4));
    138     P now=P(q[m].a,q[m].b);anss=max(q[m-1].d,q[m].d-getmax(q[m].a,q[m].b));
    139     for(i=m-1;i>=1;i--)
    140     {
    141         now=get(now,P(q[i].a,q[i].b));
    142         if(now==P(0,0))    break;
    143         anss=min(anss,max(q[i-1].d,q[m].d-getmax(now.first,now.second)));
    144     }
    145     printf("%d",anss);
    146     return 0;
    147 }

    当然还有一种方法:用树上差分显然可以O(n+m)求路径交(就是统计每个点被路径经过了几次,然后被经过次数与路径数相等的就属于路径交)

    注意到答案可以二分,然后就完了。。。。。

    。。。。代码以后再说吧

  • 相关阅读:
    中国石油昆仑加油卡
    157 01 Android 零基础入门 03 Java常用工具类01 Java异常 01 异常介绍 02 异常内容简介
    156 01 Android 零基础入门 03 Java常用工具类01 Java异常 01 异常介绍 01 Java常用工具类简介
    155 01 Android 零基础入门 02 Java面向对象 07 Java多态 07 多态知识总结 01 多态总结
    154 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 05 匿名内部类
    153 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 04 方法内部类
    152 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 03 静态内部类
    151 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类 02 成员内部类
    150 01 Android 零基础入门 02 Java面向对象 07 Java多态 06 内部类概述 01 内部类概述
    149 01 Android 零基础入门 02 Java面向对象 07 Java多态 05 接口(重点)07 接口的继承
  • 原文地址:https://www.cnblogs.com/hehe54321/p/9017766.html
Copyright © 2011-2022 走看看