【题解】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;
}

浙公网安备 33010602011771号