【洛谷1613】跑路(倍增+最短路)
大致题意: 小\(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;
}
待到再迷茫时回头望,所有脚印会发出光芒