HDU 2807 the shortest path (Shortest Path + rapid matrix comparison)

Source: Internet
Author: User

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)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.