YBTOJ 6.1例5 最短路径 题解

例3和例5都是矩阵快速幂优化dp 这里简单讲一下个人理解
实际个人理解与书中有所不同
比如假如 k 是 基数 x 乘上 res 得来的
那么实际上 \(dp[i][j][k]\) 是由 \(dp[i][j][k] = min(dp[i][p][x] + dp[p][j][res])\) 这样一个式子转移过来的 相当于是把这 k 步拆成了两半然后合起来
然后实质上就是一个二进制的优化了
code:

#include <bits/stdc++.h>
using namespace std;

const int N = 250;
const int M = 0x0d00;
int n, t, s, e;
int cnt;
int id[M];

struct matrix {
	int a[N][N];
};

matrix dp(matrix x, matrix y) {
	matrix ret;
	memset(ret.a, 0x3f, sizeof(ret.a) );
	for (int i = 1; i <= cnt; ++i) {
		for (int j = 1; j <= cnt; ++j) {
			for (int k = 1; k <= cnt; ++k) ret.a[i][j] = min(ret.a[i][j], x.a[i][k] + y.a[k][j]);
		}
	}
	return ret;
}

matrix ksm(matrix x, int k) {
	matrix ret;
	memset(ret.a, 0x3f, sizeof(ret.a) );
	for (int i = 1; i <= cnt; ++i) ret.a[i][i] = 0;
	while (k) {
		if (k & 1) ret = dp(ret, x);
		x = dp(x, x);
		k >>= 1;
	}
	return ret;
}

int main() {
	matrix ans;
	memset(ans.a, 0x3f, sizeof(ans.a) );
	scanf("%d%d%d%d", &n, &t, &s, &e);
	for (int i = 1; i <= t; ++i) {
		int x, y, z;
		scanf("%d%d%d", &z, &x, &y);
		if (id[x] == 0) id[x] = ++cnt;
		if (id[y] == 0) id[y] = ++cnt;
		ans.a[id[x]][id[y]] = z;
		ans.a[id[y]][id[x]] = z;
	}
	
	ans = ksm(ans, n);
	
	printf("%d",ans.a[id[s]][id[e]]);
	
	return 0;
}
posted @ 2023-05-24 16:36  Steven24  阅读(14)  评论(0编辑  收藏  举报