【题解】洛谷 P6190 [NOI Online #1 入门组] 魔法
前言
其实其他题解讲得很清楚了,这篇题解主要是想讲一下如何把矩阵快速幂的初始化的时间复杂度由
题解
还是先简单说一下题目解法:
首先要最优,显然
所以我们只需将
由于
P.S. 所谓的广义矩阵乘法,就是把普通矩阵乘法中求和(
考虑矩阵乘法应用在类似图论问题中的本质,发现就是信息的合并——
于是我们只需将
说明:将
因此,对于每条边
代码
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
const int max_n=100+5;
const int max_m=2500+5;
int u[max_m],v[max_m],t[max_m];
long long dis[max_n][max_n],d[max_n][max_n];
const long long inf=1e18;
struct Matrix
{
long long v[max_n][max_n];
}A,ans;
inline Matrix operator * (const Matrix &a,const Matrix &b)
{
static Matrix res;
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
{
res.v[i][j]=inf;
for(int k=1;k<=n;++k)
res.v[i][j]=min(res.v[i][j],a.v[i][k]+b.v[k][j]);
}
return res;
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
dis[i][j]=d[i][j]=(i==j?0:inf);
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",u+i,v+i,t+i);
dis[u[i]][v[i]]=t[i];
}
for(int k=1;k<=n;++k)
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
ans.v[i][j]=dis[i][j];
for(int k=1;k<=m;++k)
for(int i=1;i<=n;++i)
d[u[k]][i]=min(d[u[k]][i],-t[k]+dis[v[k]][i]);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
A.v[i][j]=d[i][j];
while(k)
{
if(k&1)
ans=ans*A;
A=A*A;
k>>=1;
}
printf("%lld\n",ans.v[1][n]);
return 0;
}