嘘~ 正在从服务器偷取页面 . . .

洛谷P1613 跑路 题解


洛谷P1613 跑路 题解

题目链接:P1613 跑路

题意

cxy 买了一个空间跑路器,每秒钟可以跑 $2^k$ 千米($k$ 是任意自然数)。

当然,这个机器是用 long long 存的,所以总跑路长度不能超过 $2^{63}-1$ 千米。

cxy 的家到公司的路可以看做一个有向图,cxy 家为点 $1$,公司为点 $n$,每条边长度均为一千米。

cxy 想每天能醒地尽量晚,所以让你帮他算算,他最少需要几秒才能到学校。

数据保证 $1$ 到 $n$ 至少有一条路径。

输入格式

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

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

输出格式

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

数据范围

$n \le 50,~m \le 10000$,最优解路径长度 $\le 2^{63}-1$。

倍增好题。注意到贪心不一定是最优的,因此考虑dp。

设 $g_{i,j,k}$ 表示 $i,j$ 之间是否存在恰好 $2^k$ 的路径,则

设 $d_{i,j}$ 为 $i,j$ 间的最短路,则 $d_{i,j} = 1$ 的充分条件为「原图存在边 $i \to j$ 或 $g_{i,j,k} = \mathtt{True}$」

注意到 $n$ 很小,所以直接 $\mathtt{Floyd}$ 即可(不会有人到这一步都没发现吧

时间复杂度 $\mathcal{O}(kn^3)$ , $k = 63$

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define rep(i,a,b) for(int i=a; i<=b; i++)
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(65))

bitset<N> g[N][N];
int n,m,d[N][N];
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> n >> m;
    memset(d,0x3f,sizeof(d));
    for(int i=1,u,v; i<=m; i++)
    {
        cin >> u >> v;
        d[u][v] = 1; g[u][v][0] = 1;
    }
    rep(k,1,63) rep(i,1,n) rep(j,1,n) rep(l,1,n)
        if(g[i][l][k-1] & g[l][j][k-1])
        { g[i][j][k] = 1; d[i][j] = 1; }
    rep(k,1,n) rep(i,1,n) rep(j,1,n)
        down(d[i][j], d[i][k] + d[k][j]);
    cout << d[1][n] << '\n';
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录