POJ 3613 Cow Relays - 倍增Floyd(矩阵加速幂)

大概是倍增Floyd的模板题。

Floyd的原理是一个一个点向图中加,k表示已经加了k个点,并且加点可以累加。(可以参考上篇博文)而这道题恰是强制加入T个点,那么我们可以将T利用一种类似于加速幂的思想向其中加点。而需要注意的是,两个数组的合并需要第三个辅助数组维护,辅助数组初值应设为无限大,用已知的两个数组去更新辅助数组,最后将辅助数组中的值赋给答案数组。
还需要注意,答案数组一开始除了自己到自己,其他的全赋为无限大,因为代价为0时每个节点可以到达的地方仅为其本身。

其实这道题本身可以用矩阵来理解,矩阵具有结合律,本题的一种路径相加也满足结合律,将矩阵乘法的定义改为取min即可(大概也是理解倍增Floyd的一种思路)。

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>

using namespace std;

const int maxn=205;

struct edge
{
    int x,y,val;
}e[maxn];

int n,cnt;
int disc[maxn<<3],map[maxn][maxn],dist[maxn][maxn],temp[maxn][maxn];

void floyd(int a[][maxn],int b[][maxn])
{
    memset(temp,0x3f,sizeof temp);//合并两种状态,必须赋初值以最大值 
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                temp[i][j]=min(temp[i][j],a[i][k]+b[k][j]);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            a[i][j]=temp[i][j];
}
int main()
{
    int k,m,S,T;z
    scanf("%d%d%d%d",&k,&m,&S,&T);
    memset(map,0x3f,sizeof map);
    memset(dist,0x3f,sizeof dist);
    for(int i=1,u,v,val;i<=m;i++)
    {
        scanf("%d%d%d",&val,&u,&v);
        e[i].x=u;e[i].y=v;e[i].val=val;
        disc[++cnt]=u;disc[++cnt]=v;
    }
    sort(disc+1,disc+cnt+1);
    n=unique(disc+1,disc+cnt+1)-(disc+1);
    S=lower_bound(disc+1,disc+n+1,S)-disc;
    T=lower_bound(disc+1,disc+n+1,T)-disc;

    //路径为0时花费均为0,所以初始状态自身到自身dist不赋值 
    for(int i=1;i<=n;i++)dist[i][i]=0;

    for(int i=1;i<=m;i++)
    {
        int x=lower_bound(disc+1,disc+n+1,e[i].x)-disc;
        int y=lower_bound(disc+1,disc+n+1,e[i].y)-disc;
        map[x][y]=map[y][x]=e[i].val;
    }
    while(k)
    {
        if(k&1)floyd(dist,map);
        floyd(map,map);
        k>>=1;
    }
    printf("%d",dist[S][T]);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值