Poj3613 Cow Relays(Floyd理解+快速幂倍增)

题意:

n个奶牛打算用T条路进行接力赛
一共有m条无向边,顶点数<=1000
给定起点st和终点ed,要求找出一条从st到ed恰好经过n条边的最短路
输出最短路距离

数据范围:n<=1e6,m<=100

解法:
floyd中,g[i][j]=min(g[i][j],g[i][k]+g[k][j])
每更新成功一次,意味着i到j之间多了一个点,也就多了一条边
第1次floyd,计算出经过2条边的最短路
第2次floyd,计算出经过3条边的最短路
第3次floyd,计算出经过4条边的最短路
...
那么第n-1次就能计算出经过n条边的最短路

每次floyd的复杂度是O(n^3),1000个点显然吃不消
但是观察到m只有100,那么最多只有200个点
可以离散化一下点的下标,这样单次floyd的复杂度就不会炸了

这样之后还不够,因为需要进行n-1次floyd,而n是1e6,还需要优化
这里可以用快速幂的倍增思路:
先讲讲floyd的具体算法实现:
初始情况下令b[][]=a[][]
c[i][j]=min(c[i][j],a[i][k]+b[k][j])
其中c是一个新数组,存储这次floyd的答案
那么c[i][j]就是经过2条边的最短路
d[i][j]=min(d[i][j],c[i][k]+c[k][j])
那么d[i][j]就是经过4条边的最短路
上述过程即倍增
那么可以利用快速幂倍增的思想:
初始情况令b[][]=a[][],假设还需要更新x次
如果x&1,那么用a取更新b,类似快速幂中的b=b*a
每次a都自行更新一次,类似快速幂中的a=a*a
每次x>>=1
这样只需要log(x)级别的次数就能计算出答案
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define int long long
const int maxm=105;
int idx[1000+5],tot;
int n,m,st,ed;
struct Node{
    int a[maxm][maxm];
    Node operator*(Node b){
        Node ans;
        for(int i=1;i<=tot;i++)for(int j=1;j<=tot;j++)ans.a[i][j]=1e18;
        for(int k=1;k<=tot;k++){
            for(int i=1;i<=tot;i++){
                for(int j=1;j<=tot;j++){
                    ans.a[i][j]=min(ans.a[i][j],this->a[i][k]+b.a[k][j]);
                }
            }
        }
        return ans;
    }
}base;
int id(int x){
    if(!idx[x])idx[x]=++tot;
    return idx[x];
}
Node ppow(Node a,int b){
    Node ans=a;
    while(b){
        if(b&1)ans=ans*a;
        a=a*a;
        b>>=1;
    }
    return ans;
}
signed main(){
    for(int i=0;i<maxm;i++)for(int j=0;j<maxm;j++)base.a[i][j]=1e18;
    cin>>n>>m>>st>>ed;
    st=id(st),ed=id(ed);
    for(int i=1;i<=m;i++){
        int z,x,y;cin>>z>>x>>y;
        x=id(x),y=id(y);
        base.a[x][y]=base.a[y][x]=min(base.a[x][y],z);
    }
    Node ans=ppow(base,n-1);
    cout<<ans.a[st][ed]<<endl;
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值