码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 3613Cow Relays( floyd 倍增法)

时间:2015-02-26 16:42:07      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:

题意:从s点出发到达e点且n条边的最短路是多少(可以走重复的路径)

图中点<=200,n<=1000,000


思路:folyd可以实现向路径中添边,但是这题与普通的求最短路问题不一样,比如从S到E经过X条边后就已经达到了最短路,这个时候仍然要强制用folyd再添边,尽管添边后就不是最短路了,但是要注意到添加的这边要使最短路损失最小,抓住这点用folyd可以实现强制添边的操作,所以可以从n=1的状态向n的状态转移


所以可以对原来的map进行n-1次folyd,但是n的范围太大,最坏的情况要进行1000000*200^3次运算肯定会T


这时,注意到可以用倍增法加速状态的转移,任何n都可以分解成2^i的和,每个2^i的状态都可以由2^(i-1)的状态直接求得。

也就是当前的map中每个点之间的距离表示经过了2^(i-1)条边,然后对当前的map folyd一次,就可以算出map中每个点之间经过了2^(i-1)+2^(i-1)=2^i 条边的最短路

所以用倍增法加速了状态转移

//628K	94MS
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
#define inf 0x3f3f3f3f
#define M 205
int n,m,st,ed;
int Hash[1005],cnt;
int mapp[M][M],tmp[M][M],n_ans[M][M];

void folyd(int a[M][M],int b[M][M],int c[M][M]){
    for(int k=1;k<=cnt;k++)
    for(int j=1;j<=cnt;j++)
    for(int i=1;i<=cnt;i++)
        if(a[j][i]>b[j][k]+c[k][i])
            a[j][i]=b[j][k]+c[k][i];

}
void map_copy(int a[M][M],int b[M][M]){
    for(int i=1;i<=cnt;i++)
    for(int j=1;j<=cnt;j++){
        a[i][j]=b[i][j];
        b[i][j]=inf;
    }
}
int main(){

    memset(mapp,0x3f,sizeof(mapp));
    memset(tmp,0x3f,sizeof(tmp));
    memset(n_ans,0x3f,sizeof(n_ans));
    for(int i=1;i<=200;i++){
        n_ans[i][i]=0;
        //注意不要让 mapp[i][i]=tmp[i][i]=0,因为要使tmp[i][i]任何时候无穷大因为自身到自身也要通过其他多个牛
        //mapp[i][j]不是inf的值表示必须存在边,不能假定自身到自身是一条权为0的边
        //n_ans[i][i]初始化自身到自身为0是动态规划的边界条件
    }
    scanf("%d%d%d%d",&n,&m,&st,&ed);
    while(m--){
        int val,u,v;
        scanf("%d%d%d",&val,&u,&v);
        if(!Hash[u]){ //对顶点离散化
            Hash[u]=++cnt;
        }
        if(!Hash[v]){
            Hash[v]=++cnt;
        }
        mapp[Hash[u] ][Hash[v] ]=mapp[Hash[v] ][Hash[u] ]=val; 
    }
    while(n){
        if(n&1){
            folyd(tmp,n_ans,mapp);
            map_copy(n_ans,tmp);
        }
        folyd(tmp,mapp,mapp);
        map_copy(mapp,tmp);
        n>>=1; //加速状态转移
    }
    printf("%d\n",n_ans[Hash[st] ][Hash[ed] ]);
    return 0;
}


POJ 3613Cow Relays( floyd 倍增法)

标签:

原文地址:http://blog.csdn.net/kalilili/article/details/43953181

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!