P1613 跑路
小A买了一个空间跑路器,每秒钟可以跑 2^k千米(k 是任意自然数)。
当然,这个机器是用longint 存的,所以总跑路长度不能超过其范围。
小A的家到公司的路可以看做一个有向图,小A 家为点 1,公司为点 n,每条边长度均为一千米。
小A想每天能醒地尽量晚,所以让你帮他算算,他最少需要几秒才能到公司。数据保证 1 到 n 至少有一条路径。
1. 倍增动态规划 + Floyd算法
int main()
{
//如果没有环,不会超过6次倍增,存在环,这里需要取到long的上限
bool reach[60][60][65];
long graph[60][60];
memset(reach,0,sizeof(reach));
memset(graph,0x3f,sizeof(graph));
int n; int m; //n个点
cin>>n>>m;
for(int i=0;i<m;i++){
int from; int to;
cin>>from>>to;
reach[from][to][0] = true;
graph[from][to] = 1;//权值皆为1
}
for(int k=0;k<64;k++)//倍增64次
for(int i=1;i<=n;i++) //遍历n个点
for(int j=1;j<=n;j++)//遍历n个点
if(reach[i][j][k]==true)//如果当前可达,尝试找下一个点进行倍增,用j作为中间点
for(int l=1;l<=n;l++){
reach[i][l][k+1]|=reach[j][l][k];
if(reach[i][l][k+1]) graph[i][l] = 1;}
//graph为最终权值图,根据该图计算最短路径
for(int k=1;k<=n;k++)//作为中间点
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
graph[i][j] = min(graph[i][j],graph[i][k]+graph[k][j]);
cout<<graph[1][n];
return 0;
}