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

时间:2021-02-14 15:10:53

题目连接: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[][];
}a,b;
int n,m,s,t,num;
matrix floyd(matrix x,matrix y)
{
matrix c;
FILL(c.dis,0x3f);
for(int k=;k<=num;k++)
for(int i=;i<=num;i++)
for(int j=;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&)
b=floyd(a,b);
a=floyd(a,a);n>>=;
}
return b;
}
int main()
{
int u,v,w;
while(scanf("%d%d%d%d",&n,&m,&s,&t)>)
{
FILL(a.dis,0x3f);FILL(b.dis,0x3f);
num=;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=;i<=num;i++)b.dis[i][i]=;
matrix ans=quick_pow(n);
printf("%d\n",ans.dis[mp[s]][mp[t]]);
}
}