【洛谷1613】跑路(倍增+最短路)

本文介绍了解决洛谷1613题的方法,通过预处理建立图结构,并利用Dijkstra算法寻找从节点1到节点n的最短路径。预处理阶段,通过检查两点之间的连接情况来更新边权,确保所有可能的连接都被考虑。最终,通过Dijkstra算法找到最小的时间单位消耗。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点此看题面

大致题意:\(A\)要从\(1\)号节点到\(n\)号节点,已知他每个单位时间可以跑\(2^k\)千米,求他最少需要多少个单位时间。

预处理

由于数据范围较小,我们可以先大力预处理。

首先,将题目中给出的边边权初始化为\(0\)

若从一点出发,到两点皆有一条边权为\(w-1\)的边,就将这两点之间连一条边权为\(k\)的边。

这样重复\(n\)次,就能保证所有该连的边都连好了。

\(Dijkstra\)跑最短路

然后,我们可以在这张图上跑最短路了。

注意,无论边权为多少,每条边长度皆为\(1\)

代码

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 50
#define Log 50
#define INF 1e9
#define add(x,y,z) !Ex[x][y][z]&&(e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].v=z,Ex[x][y][z]=1)
using namespace std;
int n,m,ee=0,lnk[N+5],Ex[N+5][N+5][Log+5];struct edge {int to,nxt,v;}e[N*N*Log+5];
class FastIO
{
    private:
        #define FS 100000
        #define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
        #define tn (x<<3)+(x<<1)
        #define D isdigit(c=tc())
        char c,*A,*B,FI[FS];
    public:
        I FastIO() {A=B=FI;}
        Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
        Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
}F;
class Dijkstra
{
    private:
        #define mp make_pair
        #define fir first
        #define sec second
        int dis[N+5],vis[N+5];typedef pair<int,int> Pr;
        priority_queue<Pr,vector<Pr>,greater<Pr> > q;
    public:
        I void Init()//初始化
        {
            for(RI w=1,i,j,k;w<=n;++w) for(i=1;i<=n;++i) for(j=1;j<=n;++j) 
                for(k=1;k<=n;++k) Ex[i][j][w-1]&&Ex[j][k][w-1]&&add(i,k,w);
        }
        I int GetAns(CI s,CI t)//最短路
        {
            RI i;Pr k;for(i=1;i<=n;++i) dis[i]=INF;dis[s]=0,q.push(mp(0,s));
            W(!q.empty())
            {
                W(!q.empty()&&vis[q.top().sec]) q.pop();if(q.empty()) break;
                for(vis[(k=q.top()).sec]=1,q.pop(),i=lnk[k.sec];i;i=e[i].nxt)
                    k.fir+1<dis[e[i].to]&&(q.push(mp(dis[e[i].to]=k.fir+1,e[i].to)),0);
            }return dis[t];
        }
}S;
int main()
{
    for(RI i=(F.read(n,m),1),x,y;i<=m;++i) F.read(x,y),add(x,y,0);//初始化边权为0
    return S.Init(),printf("%d",S.GetAns(1,n)),0;
}

转载于:https://www.cnblogs.com/chenxiaoran666/p/Luogu1613.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值