zoukankan      html  css  js  c++  java
  • POJ 3613 Cow Relays

    • 题目大意:给定起点和终点,求经过k条边的最短路

    • 思路:倍增Floyd 矩阵快速幂优化

      其实,虽然被称作倍增Floyd,但和Floyd关系好像并不大?

      按dp思想理解,设f(k,i,j)表示经过k条边从ij的最小花费,则

      (f(k,i,j)=min(f(k-1,i,p)+f(1,p,j)))

      k次Floyd显然会超时,现考虑定义新运算如下:

      对一张有n个点的图,用n*n的邻接矩阵来存储,其中(i,j)表示从i到j的最短路长度

      A矩阵表示经过x条边以后的最短路,B矩阵表示经过y条边以后的最短路

      定义新运算:(A*B=C)

      (C[i,j]=min_{k=1}^nA[i,k]+B[k,j])

      对这种矩阵运算,满足结合律,可以用类似快速幂的倍增思想进行优化

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=210;//注意空间限制 数组开大直接报错
    int s,e,k,n,m,book[3005];
    struct data {//离散化用
        int from,to,dis;
    } node[3005];
    struct Matrix {
        int mp[maxn][maxn];
        inline Matrix () {memset(mp,0x3f,sizeof(mp));}
        Matrix operator *(const Matrix &a)const {
            Matrix c;
            for(int k=1; k<=n; ++k) 
                for(int i=1; i<=n; ++i) 
                    for(int j=1; j<=n; ++j)
                        c.mp[i][j]=min(c.mp[i][j],mp[i][k]+a.mp[k][j]);
            return c;
        }
    } f,ans;
    void ksm(){
        ans=f;
        while(k) {
            if(k&1) ans=ans*f;
            f=f*f;
            k>>=1;
        }
    }
    int main() {
        scanf("%d%d%d%d",&k,&m,&s,&e);
        for(int i=1,x,y,z; i<=m; ++i) {
            scanf("%d%d%d",&z,&x,&y);
            book[++n]=x;
            book[++n]=y;
            node[i].from=x;
            node[i].to=y;
            node[i].dis=z;
        }
        sort(book+1,book+1+n);
        int tot=unique(book+1,book+1+n)-(book+1);
        for(int i=1; i<=m; ++i) {
            node[i].from=lower_bound(book+1,book+1+tot,node[i].from)-book;
            node[i].to=lower_bound(book+1,book+1+tot,node[i].to)-book;
            f.mp[node[i].from][node[i].to]=f.mp[node[i].to][node[i].from]=node[i].dis;
        }
        s=lower_bound(book+1,book+1+tot,s)-book;
        e=lower_bound(book+1,book+1+tot,e)-book;
        n=tot;
        //以上为离散化内容
        --k;//经过k条边 需要进行k-1次floyd
        ksm();
        printf("%d",ans.mp[s][e]);
        return 0;
    }
    
  • 相关阅读:
    一起复习几何(2)
    如何应用设计模式设计你的足球引擎(第三、四部分)完
    一起复习几何(1)
    链接错误C1128和LNK1210
    VS2008 在IE中 调试 ActiveX控件
    从 Chrome 谈到 Adobe
    <Dive into Python>大补贴(1)
    Debian Package 管理问题
    PXELINUX实现网络安装操作系统
    计算机世界中的道德伦理
  • 原文地址:https://www.cnblogs.com/yu-xing/p/10423708.html
Copyright © 2011-2022 走看看