ABC236G

对于一个 p×m 的矩阵 A,与 m×q 的矩阵 B,定义广义矩阵乘法 A×B=C 的结果是一个 p×q 的矩阵 C,满足:

Ci,j=(Ai,1B1,j)(Ai,2B2,j)(Ai,nBn,j)

其中 是两种二元运算。

一些约定:

  • 有交换律:ab=ba
  • 有结合律:(ab)c=a(bc)
  • 有分配律:a(bc)=(ab)(ac)

有交换律,结合律, 有分配律,那么广义的矩阵乘法就满足结合律。

下面证明 =max,=min 的广义矩阵乘法具有结合律:

首先显然 max 有交换律和结合律,那么 max(a,min(b,c))=min(max(a,b),max(a,c)) 也是显然的。

回到原问题,令 f(v,i) 表示从 1 出发,经过 i 条边到达点 v 的最早时间,w(u,v) 表示边 uv 被加入的最小时间,可以得到转移:

f(v,i)=min1un{max(f(u,i1),w(u,v))}

其中 f(1,0)=0,其余均为

不难发现这个由上面的结论可以矩阵快速幂优化:

[f(1,i)f(2,i)f(3,i)f(n,i)]=[w(1,1),w(2,1),,w(n,1)w(1,2),w(2,2),,w(n,2)w(1,3),w(2,3),,w(n,3)w(1,n),w(2,n),,w(n,n)][f(1,i1)f(2,i1)f(3,i1)f(n,i1)]

时间复杂度 O(n3logL)

Code:

#include <bits/stdc++.h>
using namespace std;
const int N = 105, inf = 0x3f3f3f3f;
int n, m, L;
struct mat {
	int a[N][N];
	
	mat operator * (const mat &x) const {
		mat res; memset(res.a, 0x3f, sizeof res.a);
		for (int i = 1; i <= n; ++i)
			for (int j = 1; j <= n; ++j)
				for (int k = 1; k <= n; ++k)
					res.a[i][j] = min(res.a[i][j], max(a[i][k], x.a[k][j]));
		return res;
	}
} f;

mat qpow(mat x, int y) {
	mat res; memset(res.a, 0x3f, sizeof res.a);
	for (int i = 1; i <= n; ++i) res.a[i][i] = 0;
	while (y) {
		if (y & 1) res = res * x;
		x = x * x;
		y >>= 1;
	}
	return res;
}

int main() {
	scanf("%d%d%d", &n, &m, &L);
	memset(f.a, 0x3f, sizeof f.a);
	for (int i = 1, u, v; i <= m; ++i) {
		scanf("%d%d", &u, &v);
		f.a[u][v] = min(f.a[u][v], i);
	}
	f = qpow(f, L);
	for (int i = 1; i <= n; ++i) printf("%d ", f.a[1][i] != inf ? f.a[1][i] : -1);
	return 0;
}
posted @   Kobe303  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示