zoukankan      html  css  js  c++  java
  • [loj539]旅游路线

    考虑枚举加油的位置,当确定某次在第$i$个位置加油后,且下一次到$j$加油,那么$i$到$j$必然会选择不超过$c_{i}$条边且最长的路径,记作$d_{i,j}$

    如果能求出$d_{i,j}$,再设$f_{q,i}$表示$q$元(恰好用完)从$i$出发的最长路,枚举$i$之后那一次加油点即可转移,由于$qle n^{2}$,因此这里的复杂度为$o(n^{4})$

    接下来,对其求一次前缀max再二分,即可对询问做到$o(tlog_{2}q)$的复杂度

    现在还有一个问题,考虑如何预处理最开始的$d_{i,j}$

    倍增,求出从$i$出发,走不超过$2^{k}$次走到$j$的最长路,通过枚举走$2^{k-1}$时的点来转移,可以做到$o(n^{3}log_{2}c_{i})$

    类似的,再对每一个点$i$做一次dp,同样枚举中专点转移即可,时间复杂度也是$o(n^{3}log_{2}c_{i})$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 105
     4 #define M 1005
     5 #define K 100005
     6 struct ji{
     7     int nex,to,len;
     8 }edge[M];
     9 struct qu{
    10     int s,q,d;
    11 }q[K];
    12 int E,n,m,t,x,y,z,head[N],p[N],c[N],g[21][N][N],ff[N],f[N][N],ans[N*N][N];
    13 void add(int x,int y,int z){
    14     edge[E].nex=head[x];
    15     edge[E].to=y;
    16     edge[E].len=z;
    17     head[x]=E++;
    18 }
    19 int main(){
    20     scanf("%d%d%d%d",&n,&m,&c[0],&t);
    21     for(int i=1;i<=n;i++){
    22         scanf("%d%d",&p[i],&c[i]);
    23         c[i]=min(c[i],c[0]);
    24         if (!p[i]){
    25             printf("orz");
    26             return 0;
    27         }
    28     }
    29     memset(head,-1,sizeof(head));
    30     for(int i=1;i<=m;i++){
    31         scanf("%d%d%d",&x,&y,&z);
    32         add(x,y,z);
    33     }
    34     memset(g,-0x3f,sizeof(g));
    35     for(int i=1;i<=n;i++){
    36         g[0][i][i]=0;
    37         for(int j=head[i];j!=-1;j=edge[j].nex)g[0][i][edge[j].to]=max(g[0][i][edge[j].to],edge[j].len);
    38     }
    39     for(int i=1;i<=20;i++)
    40         for(int x=1;x<=n;x++)
    41             for(int y=1;y<=n;y++)
    42                 for(int z=1;z<=n;z++)
    43                     g[i][x][y]=max(g[i][x][y],g[i-1][x][z]+g[i-1][z][y]);
    44     memset(f,-1,sizeof(f));
    45     for(int i=1;i<=n;i++)f[i][i]=0;
    46     for(int x=1;x<=n;x++)
    47         for(int i=0;i<=20;i++)
    48             if (c[x]&(1<<i)){
    49                 for(int y=1;y<=n;y++)ff[y]=f[x][y];
    50                 for(int y=1;y<=n;y++)
    51                     for(int z=1;z<=n;z++)
    52                         if (ff[z]!=-1)f[x][y]=max(f[x][y],ff[z]+g[i][z][y]);
    53             }
    54     memset(ans,-0x3f,sizeof(ans));
    55     for(int i=1;i<=n;i++)ans[0][i]=0;
    56     for(int i=1;i<=n*n;i++)
    57         for(int x=1;x<=n;x++)
    58             if (p[x]<=i)
    59                 for(int y=1;y<=n;y++)
    60                     if (f[x][y]!=-1)ans[i][x]=max(ans[i][x],ans[i-p[x]][y]+f[x][y]);//o(n^4)
    61     for(int i=1;i<=n*n;i++)
    62         for(int j=1;j<=n;j++)ans[i][j]=max(ans[i][j],ans[i-1][j]);
    63     for(int i=1;i<=t;i++){
    64         scanf("%d%d%d",&x,&y,&z);
    65         if (ans[y][x]<z)printf("-1
    ");
    66         else{
    67             int l=0,r=y;
    68             while (l<r){
    69                 int mid=(l+r>>1);
    70                 if (ans[mid][x]>=z)r=mid;
    71                 else l=mid+1;
    72             }
    73             printf("%d
    ",y-l);
    74         }
    75     }
    76     return 0;
    77 }
    View Code
  • 相关阅读:
    刷水题(四)
    C++如何调试
    刷水题(三)
    刷水题(二)
    虔诚的墓主人(BZOJ1227)(洛谷P2154)解题报告
    同余方程组(EXCRT)(luogu4777)
    数据结构——树状数组详解
    程序自动分析(NOI2015)(洛谷P1955)题解
    小胖的奇偶(Viojs1112)题解
    小胖守皇宫(VIJOS P1144 )题解
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14308318.html
Copyright © 2011-2022 走看看