解题报告:luogu P1613
题目链接:P1613 跑路
二进制的神奇应用。
考虑 \(dis_{i,j}\)在为 \(2^s\) 时存在,意味着存在断点 \(k\) 满足 \(dis_{i,k}\) 和 \(dis_{k,j}\) 为\(2^{s-1}\)时存在,我们根据这个东西进行递推。
然后处理出所有可行路线,进行 \(floyd\) 即可(当然 \(dij\),\(SPFA\) 啥的都行。
又没做出来,\(qwq\)......
\(Code\):
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define read(x) scanf("%d",&x)
#define ll long long
#define inf 1ll<<60
int n,m,l,r;
ll dis[55][55];
int minx[55][55][64];
int main()
{
read(n),read(m);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dis[i][j]=inf;
for(int i=1;i<=m;i++) read(l),read(r),dis[l][r]=1,minx[l][r][0]=1;
for(int s=1;s<=64;s++)
{
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++) if(minx[i][k][s-1]&&minx[k][j][s-1]) minx[i][j][s]=1,dis[i][j]=1;
}
}
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
printf("%d\n",dis[1][n]);
return 0;
}