这个东西思路还是不错的。
解法就是把矩阵幂的加法改成取min,乘法改成加法就好,和floyed是一样的。这样的话,矩阵操作一次就相当于松弛了一次最短路。
建矩阵的过程也比较简单,可以离散化,当然下面有另一种更优秀的打法,可以借鉴一下。
#include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<cstdio> #include<vector> #include<set> #include<map> #include<queue> #include<stack> using namespace std; int read(){ int sum=0,f=1;char x=getchar(); while(x<'0'||x>'9'){ if(x=='-') f=-1; x=getchar(); }while(x>='0'&&x<='9'){ sum=sum*10+x-'0'; x=getchar(); }return sum*f; } int k,m,s,e,num; int id[2000]; struct Matrix{ int x[600][600]; void add(int a,int b,int c){ x[a][b]=c; return ; } friend Matrix operator * (Matrix a,Matrix b){ Matrix c; memset(c.x,0x3f,sizeof(c.x)); for(int i=1;i<=num;i++) for(int j=1;j<=num;j++) for(int k=1;k<=num;k++) c.x[i][j]=min(c.x[i][j],a.x[i][k]+b.x[k][j]); return c; } void db(){ cout<<endl; for(int i=1;i<=num;i++){ for(int j=1;j<=num;j++) cout<<x[i][j]<<" "; cout<<endl; } } void put(int a,int b){ printf("%d",x[a][b]); return ; } }a; void qpow(int k){ Matrix c=a,b=a; // b.db(); for(;k;k>>=1,b=b*b) if(k&1) c=c*b; // c.db(); a=c; } int main(){ k=read();m=read();s=read();e=read(); memset(a.x,0x3f,sizeof(a.x)); for(int i=1,x,y,z;i<=m;i++){ z=read();x=read();y=read(); id[x]=id[x]?id[x]:++num; id[y]=id[y]?id[y]:++num; a.add(id[x],id[y],z); a.add(id[y],id[x],z); } // a.db(); qpow(k-1); // a.db(); a.put(id[s],id[e]); return 0; }
这种打法是直接用a做的初始矩阵,根据An=A*An-1做的操作,因为一开始不太清楚单位矩阵是谁。
后来想通了,以前的单位矩阵之所以是那样的,是因为单位矩阵的定义是另一个矩阵乘完该矩阵还是原矩阵,以前的之所以是对角线全是1,是因为通过矩阵乘后这个矩阵可以满足单位矩阵性质。
那么这个题的单位矩阵是正无穷矩阵,因为该任何一个矩阵乘完该矩阵还是原矩阵(因为取min嘛)。