【题解】P2886 [USACO07NOV] Cow Relays G

P2886】题解

一:【题面】

二:【解法】

f[k][i][j]:i->j路径个数为k的最短路长度
f[k][i][j]=min(f[k][i][j],f[k-1][i][a]+f[1][a][j])
更一般的f[k][i][j]=min(f[k][i][j],f[k-p][i][a]+f[p][a][j]),p任取一值

注意到,i,j固定,a滑动,与矩阵乘法原理相似,考虑矩阵快速幂加速
矩阵F(k)[i][j]:i->j路径个数为k的最短路长度

base维护2^k步最短路
F拼接base求答案

具体实现见代码

三:【代码】

#include<bits/stdc++.h>
#define inf 1e9
using namespace std;
const int N=1010;
typedef long long LL;
struct mat{
	int a[101][101];
	mat(){
		for(int i=0;i<=100;i++){
			for(int j=0;j<=100;j++){
				a[i][j]=inf;
			}
		}
	}
 	const mat operator*(const mat b)const{
 		mat ans;
		for(int i=1;i<=100;i++){
			for(int j=1;j<=100;j++){
				for(int k=1;k<=100;k++){
					ans.a[i][j]=min(ans.a[i][j],a[i][k]+b.a[k][j]);
				}
			}
		}
		return ans;
	}
};
int u[N],v[N],w[N];
int ap[N],re[N];
int cnt=0;
int main(){
	int n,t,s,e;cin>>n>>t>>s>>e;
	for(int i=1;i<=t;i++){
		cin>>w[i]>>u[i]>>v[i];
		ap[u[i]]=ap[v[i]]=1;
	}
	for(int i=1;i<=1000;i++){
		if(ap[i]==0) continue;
		re[i]=++cnt;
	}
	mat F,base;
	for(int i=1;i<=t;i++){
		u[i]=re[u[i]];
		v[i]=re[v[i]];
		base.a[u[i]][v[i]]=base.a[v[i]][u[i]]=w[i];
	}
	for(int i=1;i<=cnt;i++) F.a[i][i]=0;
	s=re[s];e=re[e];
	while(n){
		if(n&1) F=F*base;
		base=base*base;
		n>>=1;
	}
	cout<<F.a[s][e]<<"\n";
	return 0;
}
posted @ 2025-12-24 16:03  Ming3398  阅读(8)  评论(0)    收藏  举报