Link:
Http://acm.hdu.edu.cn/showproblem.php? PID = 1, 2807
Question:
The shortest path
Time Limit: 4000/2000 MS (Java/others) memory limit: 32768/32768 K (Java/Others)
Total submission (s): 1421 accepted submission (s): 436
Problem descriptionthere are n cities in the country. each city is represent by a matrix size of M * m. if City A, B and C satisfy that a * B = C, we say that there is a road from A to C with distance 1 (but that does not means there is a road from C to ).
Now the king of the country wants to ask me some problems, in the format:
Is there is a road from city X to Y?
I have to answer the questions quickly, can you help me?
Inputeach test case contains a single integer n, m, indicating the number of cities in the country and the size of each city. the next following n blocks each block stands for a matrix size of M * m. then a integer k means the number of questions the king will ask,
The following K lines each contains two integers x, y (1-based ). the input is terminated by a set starting with N = m = 0. all integers are in the range [0, 80].
Outputfor each test case, You shoshould output one line for each question the king asked, if there is a road from city X to Y? Output the shortest distance from X to Y. If not, output "sorry ".
Sample Input
3 21 12 21 11 12 24 411 33 21 12 21 11 12 24 311 30 0
Sample output
1Sorry
Question:
If matrix A * B = C, it indicates that a -- B has a unidirectional path with a distance of 1.
Give some matrices and then ask the distance between any two matrices.
Analysis and Summary:
1. The key to this question is matrix operations.
First, create a graph. Obviously, create a graph using a three-layer for loop.
The first time I did this, I put the step of multiplication in the layer-3 for loop. As a result, I submitted TLE with G ++ and 1500 MS + with C ++.
Then we found that we could put the multiplication step in the second-layer loop. The result was instantly reduced from 1500 ms to 350 MS +.
2. The above running time is based on the simple matrix comparison method.
We know that to compare the complexity of the two matrices is O (n ^ 2), is there a way to reduce it to O (n? If the complexity level is reduced, the speed improvement is objective.
Then I checked the materials and learned a method.
This method is used to multiply each matrix by a vector (this vector is <1, 2, 3, 4 ,... m>), turn this matrix into a one-dimensional identification matrix, and then use this identification matrix to determine whether the two matrices are equal. For more information, see the code.
1. Simple matrix comparison, 359 Ms
// 359 MS#include<iostream>#include<cstdio>#include<cstring>using namespace std;typedef int Type;const int INF = 0x7fffffff;const int VN = 100;struct Matrix{ Type mat[VN][VN]; int n, m; Matrix(){n=m=VN; memset(mat, 0, sizeof(mat));} Matrix(const Matrix&a){ set_size(a.n, a.m); memcpy(mat, a.mat, sizeof(a.mat)); } Matrix& operator = (const Matrix &a){ set_size(a.n,a.m); memcpy(mat, a.mat, sizeof(a.mat)); return *this; } void set_size(int row, int column){n=row; m=column;} friend Matrix operator *(const Matrix &a,const Matrix &b){ Matrix ret; ret.set_size(a.n, b.m); for(int i=0; i<a.n; ++i){ for(int k=0; k<a.m; ++k)if(a.mat[i][k]){ for(int j=0; j<b.m; ++j)if(b.mat[k][j]){ ret.mat[i][j] = ret.mat[i][j]+a.mat[i][k]*b.mat[k][j]; } } } return ret; } friend bool operator==(const Matrix &a,const Matrix &b){ if(a.n!=b.n || a.m!=b.m)return false; for(int i=0; i<a.n; ++i) for(int j=0; j<a.m; ++j) if(a.mat[i][j]!=b.mat[i][j])return false; return true; }};Matrix arr[VN];int n, m;int d[VN][VN];void init(){ for(int i=0; i<n; ++i){ d[i][i] = INF; for(int j=i+1; j<n; ++j) d[i][j] = d[j][i] = INF; }}void Floyd(){ for(int k=0; k<n; ++k) for(int i=0; i<n; ++i) for(int j=0; j<n; ++j) if(d[i][k]!=INF && d[k][j]!=INF) d[i][j] = min(d[i][j],d[i][k]+d[k][j]);}int main(){ while(~scanf("%d%d",&n,&m)&&n+m){ init(); for(int i=0; i<n; ++i){ arr[i].set_size(m,m); for(int j=0; j<m; ++j){ for(int k=0; k<m; ++k) scanf("%d",&arr[i].mat[j][k]); } } for(int i=0; i<n; ++i){ for(int j=0; j<n; ++j)if(i!=j){ Matrix ret = arr[i]*arr[j]; for(int k=0; k<n; ++k)if(k!=j&&k!=i){ if(ret==arr[k]){ d[i][k] = 1; } } } } Floyd(); scanf("%d",&m); for(int i=0; i<m; ++i){ int u,v; scanf("%d %d",&u,&v); --u, --v; if(d[u][v]!=INF) printf("%d\n",d[u][v]); else puts("Sorry"); } } return 0;}
2. Fast Matrix comparison, 62 Ms
// 62 MS#include<iostream>#include<cstdio>#include<cstring>using namespace std;typedef int Type;const int INF = 0x7fffffff;const int VN = 100;struct Matrix{ Type mat[VN][VN]; int n, m; Matrix(){n=m=VN; memset(mat, 0, sizeof(mat));} Matrix(const Matrix&a){ set_size(a.n, a.m); memcpy(mat, a.mat, sizeof(a.mat)); } Matrix& operator = (const Matrix &a){ set_size(a.n,a.m); memcpy(mat, a.mat, sizeof(a.mat)); return *this; } void set_size(int row, int column){n=row; m=column;} friend Matrix operator *(const Matrix &a,const Matrix &b){ Matrix ret; ret.set_size(a.n, b.m); for(int i=0; i<a.n; ++i){ for(int k=0; k<a.m; ++k)if(a.mat[i][k]){ for(int j=0; j<b.m; ++j)if(b.mat[k][j]){ ret.mat[i][j] = ret.mat[i][j]+a.mat[i][k]*b.mat[k][j]; } } } return ret; }}arr[VN];struct Node{ int map[VN]; void create(Matrix &a, Node &rec){ for(int i=0; i<a.n; ++i){ map[i]=0; for(int j=0; j<a.m; ++j) map[i]+=a.mat[i][j]*rec.map[j]; } }}rec[VN];int n, m;int d[VN][VN];void init(){ for(int i=0; i<n; ++i){ d[i][i] = INF; for(int j=i+1; j<n; ++j) d[i][j] = d[j][i] = INF; }}bool cmp(Node &a,Node &b,int n){ for(int i=0; i<n; ++i) if(a.map[i]!=b.map[i])return false; return true;}void Floyd(){ for(int k=0; k<n; ++k) for(int i=0; i<n; ++i) for(int j=0; j<n; ++j) if(d[i][k]!=INF && d[k][j]!=INF) d[i][j] = min(d[i][j],d[i][k]+d[k][j]);}int main(){ while(~scanf("%d%d",&n,&m)&&n+m){ init(); for(int i=0; i<n; ++i){ arr[i].set_size(m,m); for(int j=0; j<m; ++j){ rec[i].map[j]=0; for(int k=0; k<m; ++k){ scanf("%d",&arr[i].mat[j][k]); rec[i].map[j] += arr[i].mat[j][k]*(k+1); } } } for(int i=0; i<n; ++i){ for(int j=0; j<n; ++j)if(i!=j){ Node ret; ret.create(arr[i], rec[j]); for(int k=0; k<n; ++k)if(k!=j&&k!=i){ if(cmp(ret, rec[k], m)){ d[i][k] = 1; } } } } Floyd(); scanf("%d",&m); for(int i=0; i<m; ++i){ int u,v; scanf("%d %d",&u,&v); --u, --v; if(d[u][v]!=INF) printf("%d\n",d[u][v]); else puts("Sorry"); } } return 0;}
-- The meaning of life is to give it meaning.
Original
Http://blog.csdn.net/shuangde800
, By d_double (reprinted, please mark)