【POJ3613】Cow Relays

题目链接:https://www.acwing.com/problem/content/347/

题目大意:给定一张无向带权图 , 找出从 \(s\)\(e\) 恰好经过 \(n\) 条边的最短路径

solution

不难发现 , 顶点数可能很多 , 但边数不超过 100 , 因此对于节点编号应该先离散化一下

用矩阵 \(G^r\) , 表示恰好经过 \(r\) 条边的最短路 , 其中 \(G^r[i][j]\) 表示从 \(i\)\(j\) 恰好经过 \(r\) 条边的最短路径 , 显然可以得出以下推论 :

如果\(r = p + q\) , 则$$G^r[i][j] = min_{k \leq n}\left{G^p[i][k] + G^q[k][j]\right}(n为节点数量)$$

同时发现 , 这个式子满足结合律 , 因此可以用矩阵快速幂快速求出 \(G^r\) , \(G^n[s][e]\)即为题目所求

时间复杂度: \((T^3logn)\)

code

#include<bits/stdc++.h>
using namespace std;
template <typename T> inline void read(T &FF) {
	int RR = 1; FF = 0; char CH = getchar();
	for(; !isdigit(CH); CH = getchar()) if(CH == '-') RR = -RR;
	for(; isdigit(CH); CH = getchar()) FF = FF * 10 + CH - 48;
	FF *= RR;
}
inline void file(string str) {
	freopen((str + ".in").c_str(), "r", stdin);
	freopen((str + ".out").c_str(), "w", stdout);
}
const int N = 205;
int n, m, s, e, path[N][3], ni, num[N];
struct matrix{
	int g[N][N];
	matrix() {
		memset(g, 0x3f, sizeof(g));
		//for(int i = 1; i <= n; i++) g[i][i] = 0;
	}
	friend matrix operator * (const matrix &ai, const matrix &bi) {
		matrix res;
		for(int k = 1; k <= ni; k++)
			for(int i = 1; i <= ni; i++)
				for(int j = 1; j <= ni; j++)
					res.g[i][j] = min(res.g[i][j], ai.g[i][k] + bi.g[k][j]);
		return res;
	}
}base;
void cpy(matrix &ai, const matrix &bi) {
	for(int i = 1; i <= ni; i++)
		for(int j = 1; j <= ni; j++)
			ai.g[i][j] = bi.g[i][j];
}
matrix Qpow(int ki) {
	if(ki == 1) return base;
	matrix hi = Qpow(ki / 2); cpy(hi, hi * hi);
	return ki & 1 ? hi * base : hi;
}
int main() {
	//file("");
	read(n), read(m), read(s), read(e);
	for(int i = 1; i <= m; i++) {
		read(path[i][0]), read(path[i][1]), read(path[i][2]);
		num[++ni] = path[i][1], num[++ni] = path[i][2];
	}
	sort(num + 1, num + ni + 1);
	ni = unique(num + 1, num + ni + 1) - num - 1;
	//for(int i = 1; i <= n; i++) base.g[i][i] = 0;
	for(int i = 1; i <= m; i++) {
		path[i][1] = lower_bound(num + 1, num + ni + 1, path[i][1]) - num;
		path[i][2] = lower_bound(num + 1, num + ni + 1, path[i][2]) - num;
		base.g[path[i][1]][path[i][2]] = base.g[path[i][2]][path[i][1]] = path[i][0];
	}
	s = lower_bound(num + 1, num + ni + 1, s) - num;
	e = lower_bound(num + 1, num + ni + 1, e) - num;
	matrix ans = Qpow(n);
	cout << ans.g[s][e] << endl;
	return 0;
}
posted @ 2020-01-29 23:17  MagicDuck  阅读(137)  评论(0编辑  收藏  举报