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]]); } }