poj 3613 經過k條邊最短路 floyd+矩陣快速冪

http://poj.org/problem?id=3613

s->t上經過k條邊的最短路


先把1000範圍的點離散化到200中,然後使用最短路可以使用floyd,由於求的是經過k條路的最短路,跑k-1次“floyd”即可(使用矩陣快速冪的思想)。

把給定的圖轉爲鄰接矩陣,即A(i,j)=1當且僅當存在一條邊i->j。令C=A*A,那麼C(i,j)=ΣA(i,k)*A(k,j),實際上就等於從點i到點j恰好經過2條邊的路徑數(枚舉k爲中轉點)。類似地,C*A的第i行第j列就表示從i到j經過3條邊的路徑數。

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <iostream>
#include <sstream>
#include <algorithm>
using namespace std;
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define clr0(x) memset(x,0,sizeof(x))
#define clr1(x) memset(x,-1,sizeof(x))
#define eps 1e-9
const double pi = acos(-1.0);
typedef long long LL;
const int inf = 0x7fffffff;
const int maxn = 205;
map <int , int> mp;
int k,m,st,en;
int n;//floyd矩陣大小
struct Matrix{
    int mat[maxn][maxn];
    void init(){
        for(int i = 0;i < maxn;++i)
            for(int j = 0;j < maxn;++j)
                mat[i][j] = inf;
    }
};
Matrix ans,tmp,_tmp;
void copy(Matrix &b,Matrix a){
    for(int i = 1;i <= n;++i)
        for(int j = 1;j <= n;++j)
            b.mat[i][j] = a.mat[i][j];
}
void floyd(Matrix &a,Matrix b,Matrix c){
    a.init();
    for(int k = 1;k <= n;++k)
    for(int i = 1;i <= n;++i)
    for(int j = 1;j <= n;++j){
        if(b.mat[i][k] == inf || c.mat[k][j] == inf)
            continue;
        if(a.mat[i][j] > b.mat[i][k]+c.mat[k][j])
            a.mat[i][j] = b.mat[i][k]+c.mat[k][j];
    }
}
int has[1005];
void init()
{
    n = 0;
    clr0(has);
    ans.init(),tmp.init();
    for(int i = 0;i < maxn;++i)
        ans.mat[i][i] = 0;
    int u,v,w;
    for(int i = 0;i < m;++i){
        RD3(w,u,v);
        if(has[u] == 0)
            has[u] = ++n;
        if(has[v] == 0)
            has[v] = ++n;
        if(tmp.mat[has[u]][has[v]] > w)
            tmp.mat[has[v]][has[u]] = tmp.mat[has[u]][has[v]] = w;
    }
}
void work()
{
    while(k){
        if(k&1){
            copy(_tmp,ans);
            floyd(ans,_tmp,tmp);
        }
        copy(_tmp,tmp);
        floyd(tmp,_tmp,_tmp);
        k>>=1;
    }
    printf("%d\n",ans.mat[has[st]][has[en]]);
}
int main()
{
    while(~RD2(k,m)){
        RD2(st,en);
        init();
        work();
    }
    return 0;
}


發佈了165 篇原創文章 · 獲贊 1 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章