题意:求无向图s到t恰好经k条边(边可以重复)的最短路径
思路:(不是很清楚)类似于快速幂的矩阵相乘的方法,只是把相乘部分改成floyd。设ans[i][j]表示的i到j通过k条边的最短路径。
ans[i][j] =min (ans[i][k] + graph[k][j])
由快速幂可知:a^t = (t%2)?(a^t/2)^2 * a : (a^t/2)^2
在处理结点编号时,最好把他们连续化,以节约空间。
#include <iostream>
#include <string.h>
using namespace std;
#define MAXN 205
#define INF 1000000000
int n,N; //N表示连续化后的顶点数
int node[1010]; //用于连续化结点编号
int map[MAXN][MAXN], dis[MAXN][MAXN],temp[MAXN][MAXN]; //dis[i][j]存储点i到点j经 k条边 的最短路径
void floyd(int a[][MAXN],int b[][MAXN]){
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
temp[i][j]=INF;
for(int k=0;k<N;k++)
for(int i=0;i<N;i++)
for(int j=0;j<N;j++)
temp[i][j]=min(a[i][k]+b[k][j],temp[i][j]);
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
a[i][j]=temp[i][j];
}
}
}
void counts(){
while(n){
if(n%2){
floyd(dis,map);
}
floyd(map,map);
n/=2;
}
}
int main(){
int t,s,e;
cin>>n>>t>>s>>e;
N=0;
memset(node,-1,sizeof(node));
for(int i=0;i<MAXN;i++){
for(int j=0;j<MAXN;j++){
dis[i][j]=INF;
map[i][j]=INF;
dis[i][i]=0;
}
}
while(t--){
int l,a,b;
cin>>l>>a>>b;
if(node[a]==-1) node[a]=N++;
if(node[b]==-1) node[b]=N++;
map[node[a]][node[b]]=l;
map[node[b]][node[a]]=l;
}
counts();
cout<<dis[node[s]][node[e]]<<endl;
return 0;
}
/*测试:
Sample Input
2 6 6 4
11 4 6
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9
Sample Output
10
*/