跑路

洛咕

题意:小A的工作不仅繁琐,更有苛刻的规定,要求小A每天早上在\(6:00\)之前到达公司,否则这个月工资清零.可是小A偏偏又有赖床的坏毛病。于是为了保住自己的工资,小A买了一个十分牛B的空间跑路器,每秒钟可以跑\(2^k\)千米(\(k\)是任意自然数).当然,这个机器是用\(longint\)存的,所以总跑路长度不能超过\(max_{longint}\)千米.小A的家到公司的路可以看做一个有向图,小A家为点1,公司为点n,每条边长度均为一千米.小A想每天能醒地尽量晚,所以让你帮他算算,他最少需要几秒才能到公司.数据保证1到n至少有一条路径.\(n<=50,m<=10000\)

分析:倍增\(Floyd\).设\(dis[i][j]\)表示i到j最少需要几秒,\(f[i][j][p]\)表示i到j的距离是否是\(2^p\)千米.

\(f[i][j][p]|=f[i][k][p-1]\)&\(f[k][j][p-1]\),当\(f[i][j][p]\)为1时,\(dis[i][j]=1.\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int N=55;
int dis[N][N],f[N][N][N];
int main(){
	memset(dis,0x3f,sizeof(dis));//初始化无穷大
	int n=read(),m=read();
	for(int i=1;i<=m;++i){
		int a=read(),b=read();
		dis[a][b]=1;f[a][b][0]=1;//初始化
	}
	for(int p=1;p<=30;++p)
		for(int k=1;k<=n;++k)
			for(int i=1;i<=n;++i)
				for(int j=1;j<=n;++j)
					if(f[i][k][p-1]&&f[k][j][p-1]){//同时更新
						dis[i][j]=1;
						f[i][j][p]=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;
}

posted on 2019-09-30 15:38  PPXppx  阅读(166)  评论(0编辑  收藏  举报