题目链接:https://www.luogu.com.cn/problem/P2886
题目要求求出点(S,T)之间经过k条边的最短路径,而对于长度为x的最短路径矩阵和长度为y的最短路径矩阵,可得到长度为x+y的最短路径矩阵,这可以效仿矩阵乘法进行更新(满足矩阵乘法的性质)。最初的矩阵是点对之间长度为1的最短路径矩阵,可以用归纳法证明A矩阵的k次幂矩阵中(i,j)位置的元素就是点对之间经过k个点的最短路。这其实运用了倍增的思想。比如说需要经过10条边,我们就可以将十变成(1010),此时只要求经过2条边的矩阵和经过8条边的矩阵在做一次矩阵乘法即可。
有一个注意点是矩阵不能开太大。
代码如下:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ui; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define pf printf 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 #define prime1 1e9+7 9 #define prime2 1e9+9 10 #define pi 3.14159265 11 #define lson l,mid,rt<<1 12 #define rson mid+1,r,rt<<1|1 13 #define scand(x) scanf("%llf",&x) 14 #define f(i,a,b) for(int i=a;i<=b;i++) 15 #define scan(a) scanf("%d",&a) 16 #define mp(a,b) make_pair((a),(b)) 17 #define P pair<int,int> 18 #define dbg(args) cout<<#args<<":"<<args<<endl; 19 #define inf 0x3f3f3f3f 20 inline int read(){ 21 int ans=0,w=1; 22 char ch=getchar(); 23 while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();} 24 while(isdigit(ch))ans=(ans<<3)+(ans<<1)+ch-'0',ch=getchar(); 25 return ans*w; 26 } 27 int n,m,t,e; 28 const int maxn=210; 29 int Hash[maxn*5];//建立映射表 30 int tn;//点的数量 31 struct matrix{ 32 int a[maxn][maxn]; 33 matrix operator * (const matrix &x) const 34 { 35 matrix c; 36 memset(c.a,inf,sizeof(c.a));//初始结果是正无穷大矩阵,便于之后更新它 37 for(int k=1;k<=tn;k++) 38 for(int i=1;i<=tn;i++) 39 for(int j=1;j<=tn;j++) 40 { 41 c.a[i][j]=min(c.a[i][j],a[i][k]+x.a[k][j]);//当前矩阵乘以x矩阵之后的结果存放在c矩阵中 42 } 43 return c; 44 } 45 matrix() 46 { 47 for(int i=0;i<maxn;i++) 48 for(int j=0;j<maxn;j++) 49 a[i][j]=0; 50 } 51 }; 52 matrix ans,s; 53 void quick() 54 { 55 //s就相当于乘方快速幂中的基数 56 ans=s; 57 n--; 58 while(n) 59 { 60 if(n&1) ans=ans*s; 61 s=s*s; 62 n>>=1; 63 } 64 } 65 int main() 66 { 67 //freopen("input.txt","r",stdin); 68 //freopen("output.txt","w",stdout); 69 std::ios::sync_with_stdio(false); 70 n=read(),t=read(),m=read(),e=read(); 71 int u,v,w; 72 memset(s.a,inf,sizeof(s.a)); 73 f(i,1,t) 74 { 75 w=read(),u=read(),v=read(); 76 if(!Hash[u])Hash[u]=++tn;//建立映射 77 if(!Hash[v])Hash[v]=++tn; 78 s.a[Hash[u]][Hash[v]]=s.a[Hash[v]][Hash[u]]=w; 79 } 80 quick(); 81 pf("%d",ans.a[Hash[m]][Hash[e]]); 82 }