简单矩阵乘法
可以矩阵套矩阵,也可以只建一个矩阵
std写得是矩阵套矩阵的写法
第一个矩阵(最大的矩阵)
矩阵大小:
矩阵意义:对于代表从i走到j需要的最少体力
矩阵嵌套:对于是一个小矩阵,小矩阵定义参见下方
第二个矩阵(小矩阵)
矩阵大小:
矩阵意义:对于代表走过新路的第i条到第j条的最少体力
矩阵转移
见代码
std
#include<bits/stdc++.h>
using namespace std;
long long n,m,k,a,b;
struct ppp {
long long f[12][12];
ppp operator*(const ppp x) {
ppp y;
memset(y.f,10,sizeof(y.f));
for(long long i=0; i<=b; i++)
for(long long j=i; j<=b; j++)
for(long long k=i; k<=j; k++)
y.f[i][j]=min(y.f[i][j],f[i][k]+x.f[k][j]);
return y;
}
};
ppp Min(ppp x,ppp y) {
for(long long i=0; i<=b; i++)
for(long long j=0; j<=b; j++)
x.f[i][j]=std::min(x.f[i][j],y.f[i][j]);
return x;
}
struct oppo {
ppp f[30][30];
oppo operator*(const oppo x) {
oppo y;
memset(y.f,10,sizeof(y.f));
for(long long k=1; k<=n; k++)
for(long long i=1; i<=n; i++)
for(long long j=1; j<=n; j++)
y.f[i][j]=Min(f[i][k]*x.f[k][j],y.f[i][j]);
return y;
}
} cs,ans;
void ksm(long long g) {
memset(ans.f,10,sizeof(ans.f));
for(long long i=1; i<=n; i++)
ans.f[i][i].f[0][0]=0;
while(g) {
if(g&1) ans=ans*cs;
g>>=1;
cs=cs*cs;
}
long long st=LONG_LONG_MAX;
for(long long j=1; j<=n; j++)
st=min(st,ans.f[1][j].f[0][b]);
if(st!=ans.f[0][0].f[0][0]) cout<<st<<"\n";
else puts("-1");
}
int main() {
cin>>n>>m>>k>>a>>b;
memset(cs.f,10,sizeof(cs.f));
for(long long i=1; i<=m; i++) {
long long s,t,u;
scanf("%lld%lld%lld",&s,&t,&u);
for(long long j=0; j<=b; j++)
cs.f[s][t].f[j][j]=u;
}
for(long long i=1; i<=a; i++) {
long long s,t,u;
scanf("%lld%lld",&s,&t);
for(long long j=1; j<=b; j++) {
scanf("%lld",&u);
cs.f[s][t].f[j-1][j]=u;
}
}
ksm(k+b);
return 0;
}
京公网安备 11010502036488号