zoukankan      html  css  js  c++  java
  • 洛谷P1613 跑路

    P1613 跑路

    题目描述

    小A的工作不仅繁琐,更有苛刻的规定,要求小A每天早上在6:00之前到达公司,否则这个月工资清零。可是小A偏偏又有赖床的坏毛病。于是为了保住自己的工资,小A买了一个十分牛B的空间跑路器,每秒钟可以跑2^k千米(k是任意自然数)。当然,这个机器是用longint存的,所以总跑路长度不能超过maxlongint千米。小A的家到公司的路可以看做一个有向图,小A家为点1,公司为点n,每条边长度均为一千米。小A想每天能醒地尽量晚,所以让你帮他算算,他最少需要几秒才能到公司。数据保证1到n至少有一条路径。

    输入输出格式

    输入格式:

    第一行两个整数n,m,表示点的个数和边的个数。

    接下来m行每行两个数字u,v,表示一条u到v的边。

    输出格式:

    一行一个数字,表示到公司的最少秒数。

    输入输出样例

    输入样例#1:
    4 4
    1 1
    1 2
    2 3
    3 4
    
    输出样例#1:
    1

    说明

    【样例解释】

    1->1->2->3->4,总路径长度为4千米,直接使用一次跑路器即可。

    【数据范围】

    50%的数据满足最优解路径长度<=1000;

    100%的数据满足n<=50,m<=10000,最优解路径长度<=maxlongint。

    /*
        这道题目是最短路径与倍增算法的综合运用。
        我们知道Floyed求最短路径的原理是用一个点k来修改i到j的最短距离。在这道题中,我们要灵活地用到这个方法。
        因为本题中小A每秒可以跑2^k(k为任意数),所以直接求最短路径是不对的。我们可以与处理出小A1秒钟可以到达的边,这个用Floyed实现,再用一个Floyed或spfa求出1到n的最短路径就可以了。
        那么关键就是如何进行预处理呢?
        我们可以用一个数组F来记录,F[u][v][i]表示u到v能否通过2^i到达,这也就是1秒。在读入的时候我们就可以得出F[u][v][0]的值,然后从1~32(因为maxlongint就是2^31)枚举i,同时枚举u和v,借助Floyed用第三个点来修改的这种思想,我们再枚举一个点k,若F[u][k][i-1]和F[k][v][i-1]同时为真,则说明F[u][v][i]为真(因为2^(i-1)+2^(i-1)=2*i)。这样我们就可以与处理出所有1秒可以到的边。
        然后再跑一边最短路就可以了。
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int map[51][51];
    bool f[51][51][40];
    int main(){
        int n,m,x,y;
        memset(map,127/3,sizeof(map));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&x,&y);
            map[x][y]=1;
            f[x][y][0]=1;
        }
        for(int w=1;w<=36;w++)
            for(int k=1;k<=n;k++)
                for(int i=1;i<=n;i++)
                    for(int j=1;j<=n;j++)
                        if(f[i][k][w-1]==1&&f[k][j][w-1]==1){
                            f[i][j][w]=1;
                            map[i][j]=1;
                        }
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++){
                    //if(i==k||i==j||j==k)continue;
                    map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
                }
        cout<<map[1][n];
    }
  • 相关阅读:
    CodeForces 156B Suspects(枚举)
    CodeForces 156A Message(暴力)
    CodeForces 157B Trace
    CodeForces 157A Game Outcome
    HDU 3578 Greedy Tino(双塔DP)
    POJ 2609 Ferry Loading(双塔DP)
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛十六进制转换成十进制
  • 原文地址:https://www.cnblogs.com/thmyl/p/7468924.html
Copyright © 2011-2022 走看看