zoukankan      html  css  js  c++  java
  • Luogu P1613跑路【倍增】By cellur925

    题目传送门

    开始的思路:直接跑一遍最短路,得到最短路的那个值。然后把那个值进行一下二进制拆分,看能拆几次。(可能是受到了刚做过的题影响)

        for(int i=30;i>=0;i--)
        {
            if((1<<i)>qwq) continue;
            //printf("%d
    ",i);
            qwq-=(1<<i);ans++;
        }

    (二进制拆分从大到小趋近)

    但实际上貌似是审错题了...只有在两点最短距离为$2^k$时才能用加速器。那么我们就需要枚举所有点对,看他们的 距离是否为$2^k$,是的话才能向他们之间连一条边。由于输出的边距离都为$2^0$,所以可以直接连边。这部分是一个运用到$floyd$思想、倍增思想的判断dp,如果若两个点能以两段2的k-1次方的距离相互到达,那么两个点就能以2的k次方的距离相互到达。(引用dalao@ GoldenPotato )。

    之后我们就跑一遍$floyd$即可(本题数据范围为50)

    Code

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 
     5 using namespace std;
     6 
     7 int n,m;
     8 int dis[100][100];
     9 bool valid[100][100][40];
    10 
    11 int main()
    12 {
    13     scanf("%d%d",&n,&m);
    14     memset(dis,0x3f,sizeof(dis));
    15     for(int i=1;i<=m;i++)
    16     {
    17         int x=0,y=0;
    18         scanf("%d%d",&x,&y);
    19         dis[x][y]=1;valid[x][y][0]=1;
    20     }
    21     for(int h=1;h<=30;h++)
    22         for(int k=1;k<=n;k++)
    23             for(int i=1;i<=n;i++)
    24                 for(int j=1;j<=n;j++)
    25                     if(valid[i][k][h-1]&&valid[k][j][h-1])
    26                         valid[i][j][h]=1,dis[i][j]=1;
    27     for(int k=1;k<=n;k++)
    28         for(int i=1;i<=n;i++)
    29             for(int j=1;j<=n;j++)
    30                 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
    31     printf("%d",dis[1][n]);
    32     return 0;
    33 }
    View Code
  • 相关阅读:
    剑指offer思路总结
    redis为什么设计成单线程
    vscode 常用工具
    redis 数据结构的实现
    记一次rm -rf 的悲伤故事
    netstate端口连接状态
    查询mysql最后更新时间
    boost库安装
    docker镜像不支持常用命令
    消息队列--线程安全
  • 原文地址:https://www.cnblogs.com/nopartyfoucaodong/p/9723575.html
Copyright © 2011-2022 走看看