洛谷P1613 跑路——倍增处理是否存在2^t的路径,最短路

题目:https://www.luogu.org/problemnew/show/P1613

分析:

《最优乘车》(http://www.sqyoj.club/problem.php?id=1005),对本题有帮助。题解见我的博客https://blog.csdn.net/qq_36314344/article/details/88585689

不能直接求最短路。因为两点间距离为2^t时,可以一秒直达,否则要进行2进制拆分。例如,点1到点n距离是8,则1秒直达;距离是7,则要3秒才能到达。

所以我们先对图进行处理,计算出两点间多少秒能到过,从而想到倍增。为此引入布尔数组f[i][j][t],表示点i,j之间存在长度为2^t的路径,从而可以实现倍增打表,转移方程为f[i][j][t]=f[i][k][t-1]&&f[k][j][t-1]。

因为需要表示两点间有没有连通,为此引入int数组g[i][j],表示点i,j之前的距离,因为松驰的需要,首先初始化g为一个比较大的数——不可过大,否则两个很大的数相加,成了一个负数。

倍增之后,再求最短路,因为最多50个点,所以可以用floyed算法。

AC代码:

#include<cstdio>
#include<iostream>
#include<cstring> 
using namespace std;
const int Maxn=51;
int n,m,x,y,g[Maxn][Maxn],f[Maxn][Maxn][32];
//g[i][j]表示点i,j之的距离
//f[i][j][t]=1表示点i,j之间有2^t的距离的路径 
int main(){
	cin>>n>>m;
	memset(g,0x7,sizeof(g));
	for(int i=1;i<=m;i++){
		scanf("%d%d",&x,&y);
		g[x][y]=f[x][y][0]=1;
	}
	for(int t=1;t<=32;t++)
		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][t-1] && f[k][j][t-1])
						g[i][j]=f[i][j][t]=1;
	for(int k=1;k<=n;k++)//阶段
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				if(g[i][k]+g[k][j]<g[i][j])
					g[i][j]=g[i][k]+g[k][j];
	cout<<g[1][n];
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值