• 2014 Super Training #10 G Nostop --矩阵快速幂


    原题: FZU 2173 http://acm.fzu.edu.cn/problem.php?pid=2173

    一开始看到这个题毫无头绪,根本没想到是矩阵快速幂,其实看见k那么大,就应该想到用快速幂什么的,况且n<=50,可以用矩阵来表示图。

    1.为什么能用矩阵快速幂呢?

    原理:

    原始矩阵m[][]中,m[u][v]代表u到v的花费,求矩阵的k次幂后,此时m[u][v]代表,从u走向b经过v步的最少花费
    注意此时矩阵的相乘应该写成:
    m[a][b]=min(m[a][1]+m[1][b],...m[a][n]+m[n][b])  ,即取最小值而非相加。

    2.为什么呢?

    m的1次方,无疑是正确的。

    m的2次方
    此时(m[a][b])^2=min(m[a][1]+m[1][b],..m[a][n]+m[n][b]),就是枚举a经过1到n点再到b的最少花费,就是a经过两步到达b的最少花费


    归纳法:

    如果(m[a][b])^i代表了a走i步到达b的最少花费,则m^(i+1)=min((m[a][1])^i+m[1][b],...(m[a][n])^i+m[n][b])

    所以可以这样做。

    (借鉴nothing的博客)

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    #define Mod 1000000007
    #define lll __int64
    using namespace std;
    #define N 6007
    
    struct Matrix
    {
        lll m[55][55];
    };
    int n,h,k;
    
    Matrix Mul(Matrix a,Matrix b)
    {
        Matrix c;
        memset(c.m,-1,sizeof(c.m));
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {
                for(int k=0;k<n;k++)
                {
                    if(a.m[i][k]!=-1&&b.m[k][j]!=-1)
                    {
                        if(c.m[i][j] == -1)
                            c.m[i][j] = a.m[i][k]+b.m[k][j];
                        else
                            c.m[i][j] = min(c.m[i][j],a.m[i][k]+b.m[k][j]);
                    }
                }
            }
        return c;
    }
    
    Matrix fastm(Matrix a,int n)
    {
        if(n == 1)
            return a;
        Matrix res = fastm(a,n/2);
        res = Mul(res,res);
        if(n&1)
            res = Mul(res,a);
        return res;
    }
    
    Matrix MPow(Matrix a,int n)  //第二种写法
    {
        Matrix res = a;
        n--;
        while(n)
        {
            if(n&1)
                res = Mul(res,a);
            n>>=1;
            a = Mul(a,a);
        }
        return res;
    }
    
    int main()
    {
        int t,i,j,k;
        int u,v;
        lll w;
        Matrix A,ans;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d",&n,&h,&k);
            memset(A.m,-1,sizeof(A.m));
            for(i=0;i<h;i++)
            {
                scanf("%d%d%I64d",&u,&v,&w);
                u--,v--;
                if(A.m[u][v] == -1)
                    A.m[u][v] = w;
                else
                    A.m[u][v] = min(A.m[u][v],w);
            }
            ans = MPow(A,k);
            printf("%I64d
    ",ans.m[0][n-1]);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    测试开发题目整理(二)
    测试开发题目整理(一)
    Python + request接口测试中Cookie和Session的获取和使用
    requests发送HTTPS请求(处理SSL证书验证)
    js ES5面向对象继承 模仿ES6
    如何使用canvas绘制椭圆,扩展非chrome浏览器中的ellipse方法
    javascript对象创建及继承
    观察者模式及事件与委托的区别-20171215内训会
    html5悬浮球效果
    文本框高度自适应不出滚动条
  • 原文地址:https://www.cnblogs.com/whatbeg/p/3832404.html
Copyright © 2020-2023  润新知