zoukankan      html  css  js  c++  java
  • 【BZOJ】1706: [usaco2007 Nov]relays 奶牛接力跑

    【题意】给定m条边的无向图,起点s,终点t,要求找出s到t恰好经过n条边的最短路径。n<=10^6,m<=100。

    【算法】floyd+矩阵快速幂

    【题解】

    先对点离散化,得到点数N。

    对初始边建立初始矩阵,然后考虑每次多跑一条边相当于一次矩阵乘法,即c[i][j]=min(a[i][k],a[k][j]),k=1~N。

    定义了矩阵乘法,就可以用矩阵快速幂优化了。

    初始矩阵ans[i][i]=0,转移矩阵a[i][i]=inf,这样就是恰好n条边。(如果a[i][i]=0就是<=n条边)

    复杂度O(N^3*log n)。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    using namespace std;
    const int N=210;//Òª¿ªÁ½±¶¡£ 
    typedef int mat[N][N];
    mat a,c,ans;
    int n,m,s,t,cnt=0,z[1010];
    int read()
    {
        char c;int s=0,t=1;
        while(!isdigit(c=getchar()))if(c=='-')t=-1;
        do{s=s*10+c-'0';}while(isdigit(c=getchar()));
        return s*t;
    }
    void mul(mat a,mat b){
        memset(c,0x3f,sizeof(c));
        for(int i=1;i<=cnt;i++){
            for(int j=1;j<=cnt;j++){//iºÍjÒ»ÑùÒ²ÊÇ¿ÉÒÔÈÆһȦ»ØÀ´µÄ¡£ 
                for(int k=1;k<=cnt;k++)c[i][j]=min(c[i][j],a[i][k]+b[k][j]);
            }
        }
        for(int i=1;i<=cnt;i++)for(int j=1;j<=cnt;j++)a[i][j]=c[i][j];
    }
    int main(){
        n=read();m=read();s=read();t=read();
        memset(a,0x3f,sizeof(a));
        for(int i=1;i<=m;i++){
            int w=read(),u=read(),v=read();//ȨֵÔÚµÚһλ£¡£¡£¡ 
            if(!z[u])z[u]=++cnt;if(!z[v])z[v]=++cnt;
            u=z[u];v=z[v];
            a[u][v]=a[v][u]=min(a[u][v],w);
        }
        memset(ans,0x3f,sizeof(ans));
        for(int i=1;i<=cnt;i++)ans[i][i]=0;
        while(n){
            if(n&1)mul(ans,a);
            mul(a,a);
            n>>=1;
        }
        printf("%d",ans[z[s]][z[t]]);
        return 0;
    }    
    View Code
  • 相关阅读:
    04: vue生命周期和实例属性和方法
    03: vuejs 事件、模板、过滤器
    (打补丁 )patch
    zabbix安装
    zabbix简介
    linux 虚拟网络模型介绍
    虚拟化
    虚拟化分类(半虚拟化和全虚拟化)
    playbook详解—YAML格式的文本
    ansible的介绍和一些基本模块介绍
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7590255.html
Copyright © 2011-2022 走看看