zoukankan      html  css  js  c++  java
  • 洛谷P2886 [USACO07NOV]牛继电器Cow Relays

    题意很简单,给一张图,把基本的求起点到终点最短路改成求经过k条边的最短路。

    求最短路常用的算法是dijkstra,SPFA,还有floyd。

    考虑floyd的过程:

    c[i][j]=min(c[i][j],a[i][k]+b[k][j]);

    自然而然联想到矩阵乘法,每次加入一个点就相当于多加一条边,那么加k次就是k条边的最短路。

    但是k可能很大(见数据范围),那么显然直接循环矩乘k次是行不通的,于是就想到了矩阵快速幂。

    和普通快速幂一样的方式,只不过是把乘法替换成矩乘。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cmath>
    using namespace std;
    int n,t,s,e,num;
    int p[2001];
    struct M{
        long long v[201][201];
    };
    M gra,ans;
    M cheng(M a,M b){
        M kk;
        memset(kk.v,0x3f,sizeof(kk.v));
        for(int k=1;k<=num;k++){
            for(int i=1;i<=num;i++){
                for(int j=1;j<=num;j++){
                    kk.v[i][j]=min(kk.v[i][j],a.v[i][k]+b.v[k][j]);
                }
            }
        }
        return kk;
    }
    void ks(int x){
        while(x){
            if(x&1){
                ans=cheng(gra,ans);
            }
            gra=cheng(gra,gra);
            x>>=1;
        }
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&t,&s,&e);
        memset(gra.v,0x3f,sizeof(gra.v));
        memset(ans.v,0x3f,sizeof(ans.v));
        for(int i=1;i<=t;i++){
            int a,b;
            long long c;
            scanf("%lld%d%d",&c,&a,&b);
            if(!p[a])p[a]=++num;
            if(!p[b])p[b]=++num;
            gra.v[p[a]][p[b]]=gra.v[p[b]][p[a]]=min(gra.v[p[b]][p[a]],c);
        }
        for(int i=1;i<=num;i++)ans.v[i][i]=0;
        ks(n);
        printf("%lld",ans.v[p[s]][p[e]]);
        return 0;
    }
  • 相关阅读:
    jsp第四次
    jsp第二次作业
    jsp第一次作业
    软件测试课堂练习
    11.11日
    10.28
    10.25
    10.21
    jsp第七周作业
    JSP第六周作业
  • 原文地址:https://www.cnblogs.com/chloris/p/10449706.html
Copyright © 2011-2022 走看看