【Ybtoj 第25章例5】最短路径【矩阵快速幂】

在这里插入图片描述

在这里插入图片描述


解题思路

考虑DP,设 f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]表示从i到j走k条路的最短路径长度,易得转移方程:
f [ i ] [ j ] [ k ] = m i n ( f [ i ] [ t ] [ k − 1 ] + f [ t ] [ j ] [ 1 ] ) f[i][j][k]=min(f[i][t][k-1]+f[t][j][1]) f[i][j][k]=min(f[i][t][k1]+f[t][j][1])
因为在转移时 k k k只与 k − 1 k-1 k1有关,所以可以化简掉第三维 f [ i ] [ j ] = m i n ( f [ i ] [ t ] + f [ t ] [ j ] ) f[i][j]=min(f[i][t]+f[t][j]) f[i][j]=min(f[i][t]+f[t][j])。这个形式与矩阵快速幂类似,所以走n条路就等价于把状态数组视为矩阵进行n次的矩阵乘幂,最后答案为 f [ s ] [ e ] f[s][e] f[s][e]

PS:需要离散化!!


代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#define ll long long
#define ldb long double
using namespace std;


int n,t,s,e,w,x,y,tot,num[10010];

struct c{
	int a[500][500];
}A,B;

c operator *(const c &A,const c &B){
	c CC;
	memset(CC.a,0x3f,sizeof(CC.a));
	for(int k=1;k<=tot;k++)
		for(int i=1;i<=tot;i++)
			for(int j=1;j<=tot;j++)
				CC.a[i][j]=min(CC.a[i][j],A.a[i][k]+B.a[k][j]);
	return CC;
}

void poww(int x){
	
	if(x==1)
	{
		B=A;
		return;
	}
	poww(x>>1);
	B=B*B;
	if(x&1)
		B=B*A;
		
}

int main(){
	memset(A.a,0x3f,sizeof(A.a));
	memset(B.a,0x3f,sizeof(B.a));
	scanf("%d%d%d%d",&n,&t,&s,&e);
	for(int i=1;i<=t;i++)
	{
		scanf("%d%d%d",&w,&x,&y);
		if(!num[x])
			num[x]=++tot;
		if(!num[y])
			num[y]=++tot;
		A.a[num[x]][num[y]]=A.a[num[y]][num[x]]=w;
	}
	poww(n);

	printf("%d",B.a[num[s]][num[e]]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值