poj3613(恰经过N条边的最短路)

 

题目连接:http://poj.org/problem?id=3613

题意:从S 到 T 经过边得个数恰为k的最短路是多少。

分析:01邻接矩阵A的K次方C=A^K,C[i][j]表示i点到j点正好经过K条边的路径数,把乘法改为加法,相当于k次Floyd,最后矩阵快速幂优化。

 

#include <cstdio>

#include <cstring>

#include <string>

#include <cmath>

#include <iostream>

#include <algorithm>

#include <queue>

#include <cstdlib>

#include <stack>

#include <vector>

#include <set>

#include <map>

#define LL long long

#define mod 100000000

#define inf 0x3f3f3f3f

#define eps 1e-9

#define N 1000010

#define FILL(a,b) (memset(a,b,sizeof(a)))

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

#define PII pair<int,int>

using namespace std;

struct matrix

{

    int dis[222][222];

}a,b;

int n,m,s,t,num;

matrix floyd(matrix x,matrix y)

{

    matrix c;

    FILL(c.dis,0x3f);

    for(int k=1;k<=num;k++)

    for(int i=1;i<=num;i++)

    for(int j=1;j<=num;j++)

    {

        if(x.dis[i][k]+y.dis[k][j]<c.dis[i][j])

            c.dis[i][j]=x.dis[i][k]+y.dis[k][j];

    }

    return c;

}

matrix quick_pow(int n)

{

    while(n)

    {

        if(n&1)

            b=floyd(a,b);

        a=floyd(a,a);n>>=1;

    }

    return b;

}

int main()

{

    int u,v,w;

    while(scanf("%d%d%d%d",&n,&m,&s,&t)>0)

    {

        FILL(a.dis,0x3f);FILL(b.dis,0x3f);

        num=0;map<int,int>mp;

        while(m--)

        {

            scanf("%d%d%d",&w,&u,&v);

            if(mp.find(u)==mp.end())mp[u]=++num;

            if(mp.find(v)==mp.end())mp[v]=++num;

            a.dis[mp[u]][mp[v]]=a.dis[mp[v]][mp[u]]=min(a.dis[mp[u]][mp[v]],w);

        }

        for(int i=1;i<=num;i++)b.dis[i][i]=0;

        matrix ans=quick_pow(n);

        printf("%d\n",ans.dis[mp[s]][mp[t]]);

    }

}
View Code

 

你可能感兴趣的:(poj)