HDU 2807 The Shortest Path:最短路+矩阵快速比较

链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2807

题目:

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 Description
There 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 A).
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?

Input
Each 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].

Output
For each test case, you should 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 2
1 1
2 2
1 1
1 1
2 2
4 4
1
1 3
3 2
1 1
2 2
1 1
1 1
2 2
4 3
1
1 3
0 0

Sample Output

1
Sorry

题目大意:

如果矩阵A*B=C,那么就表示A--》B有一条单向路径,距离为1.

给一些矩阵,然后问任意两个矩阵直接的距离。

分析与总结:

1. 这题的关键在于矩阵运算。

首先是建图, 显然,建图要用3层for循环。

第一次我做的时是把相乘的那一步放在第三层for循环里,结果导致用G++提交TLE, 用C++提交用了1500MS+.

然后发现其实可以把相乘那一步放在第二层循环里的,结果瞬间从1500MS 降到了350MS+

2. 以上的运行时间都是基于朴素的矩阵比较方式。

我们知道要比较两个矩阵的复杂度是O(n^2), 那么有没有办法降到O(n)呢? 复杂度降了一阶,那速度的提升是很客观的。

然后查了下资料,学习了一种方法。

这个方法主要是让每个矩阵乘上一个向量(这个向量是<1,2,3,4,...m>),让这个矩阵变成一个一维的标识矩阵,之后就利用这个标识矩阵来判断两个矩阵是否相等。具体看代码。

1.朴素的矩阵比较, 359MS

//  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. 快速矩阵比较, 62MS

更多精彩内容:http://www.bianceng.cn/Programming/sjjg/

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索int
, 矩阵
, matrix
, java 矩阵
, const
, mat
, 矩阵运算
, single ask
The
hdu快速幂、矩阵快速幂、矩阵快速幂模板、稀疏矩阵快速转置算法、快速矩阵乘法,以便于您获取更多的相关知识。

时间: 2024-12-31 19:53:48

HDU 2807 The Shortest Path:最短路+矩阵快速比较的相关文章

hdu 2807 The Shortest Path

点击打开链接hdu 2807 思路:最短路+floyd+矩阵乘法 分析: 1 题目明确要求x->y是否有了,而且有多次询问,所以序则floyd 2 题目给的点的形式是矩阵,所以还要去处理矩阵,判断A*B=C 3 题目说了A B C三个城市,所以做A B C三个是不同的 代码: #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> using namespace

矩阵快速幂专题【完结】

第一题 hdu 1757 A Simple Math Problem 点击打开链接 思路:矩阵快速幂 分析: 1 最简单的矩阵快速幂的题目,直接利用矩阵求解即可 点击打开查看代码 第二题 hdu 1575 Tr A 点击打开hdu 1575 思路: 矩阵快速幂 分析: 1 题目给定一个n*n的矩阵要求矩阵的k次幂之后的矩阵的对角线的和 2 矩阵快速幂的裸题 点击打开查看代码 第三题 hdu 2604 Queuing 点击打开hdu 2604 思路: 递推+矩阵快速幂 分析; 1 根据题目的意思,

UVa 10229 Modular Fibonacci:矩阵快速幂求斐波那契

10229 - Modular Fibonacci Time limit: 3.000 seconds http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=115&page=show_problem&problem=1170 The Fibonacci numbers (0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...) are defin

c语言-关于矩阵快速转置算法问题

问题描述 关于矩阵快速转置算法问题 请问圈出的部分是什么意思啊 解决方案 图片看不清,应该和这个类似,而且有详细注释:http://programdesign.baike.com/article-379765.html 解决方案二: 7. 矩阵的快速转置算法矩阵的快速转置矩阵的快速转置

hdu 3631 Shortest Path

点击打开链接hdu 3631 思路:最短路+floyd 分析: 1 题目给的n <= 300,而边数m<=100000,并且有Q<= 100000次询问.刚开始我用优先队列+Dij然后就开始TLE,然后就没然后了. 2 看了题解之后猛然发现这尼玛就是floyd,(对算法理解不透测).我们知道floyd就是每次都拿一个中间点k来更新dis,题目中是只有标记过的点才能够使用,那么就像floyd一样只要是标记来这个点那么就可以用这个点来进行更新dis,然后如果要求两点直间的距离只要查找即可.

HDU 3339 In Action:最短路+背包

链接: http://acm.hdu.edu.cn/showproblem.php?pid=3339 题目: Problem Description Since 1945, when the first nuclear bomb was exploded by the Manhattan Project team in the US, the number of nuclear weapons have soared across the globe. Nowadays,the crazy bo

HDU 3936 斐波那契性质矩阵连乘

题意:p[i]=fib[4*i-1] 给出L,R,求出中间的p[i]的和. 利用性质:p[1]+p[2]+...+p[n]=f[1]^2+f[2]^2+...+f[2*n-1]^2+f[2*n]^2=f[2*n]*f[2*n+1] fibonacci数列的性质: 1.gcd(fib(n),fib(m))=fib(gcd(n,m)) 证明:可以通过反证法先证fibonacci数列的任意相邻两项一定互素,然后可证n>m时gcd(fib(n),fib(m))=gcd(fib(n-m),fib(m)),

PKU 3233 Matrix Power Series(矩阵快速幂 二分)

点击打开链接 Matrix Power Series Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 19189   Accepted: 8099 Description Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + - + Ak. Input The input contains exactly one t

10299 Problem A: Modular Fibonacci(斐波那契的矩阵快速幂)

Problem A: Modular Fibonacci The Fibonacci numbers (0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ...) are defined by the recurrence: F0 = 0 F1 = 1 Fi = Fi-1 + Fi-2 for i>1 Write a program which calculates Mn = Fn mod 2m for given pair of n and m. 0 n 2147483