SPFA算法+A*启发式搜索。
1.考虑建立反图,然后跑最短路算法得到以tt为根的最短路径生成树。
2.A*启发式搜索计算第K最短路的长度。
注意:1.最多求出经由的K条路,若大于K条路,就不再往下走了
2.如果起点终点相同,则K+1
以POJ 2449为模板的S->T的K短路。
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;
#define INF 0x3f3f3f3f
const int N=1100;
typedef struct nnn{ //定义优先队列的元素类型
int F,G,s; //对应节点s,起点至该节点的距离G,经过s的路长F
friend bool operator < (nnn a,nnn b){
return a.F>b.F;
}
}PATH;
typedef struct nn{ //邻接表节点的结构定义。
int v,w; //邻接点V,边长W。
}node;
vector<node> map[N],tmap[N];//邻接表map,辅助邻接表tmap,
int H[N]; //反向距离表,即end至节点i的距离为H[i]
void findH(int s){ //SPFA算法计算s可达的每个点的距离值H[]
queue<int> q;
int vis[N]={0}; //设所有节点非队列元素标志
q.push(s);vis[s]=1;H[s]=0;//s进入队列,距离值为0
while(!q.empty()){
s=q.front();
q.pop();
vis[s]=0;
int m=tmap[s].size();
for(int i=0;i<m;i++){
int j=tmap[s][i].v;
if(H[j]>tmap[s][i].w+H[s]){
H[j]=tmap[s][i].w+H[s];
if(!vis[j]) vis[j]=1,q.push(j);
}
}
}
}
int Astar(int st,int en,int K){//计算st至en的第k短的路径长度
priority_queue<PATH> q;
PATH p,tp; //被扩展的元素p,被扩展的新元素tp
int k[N]={0}; //计算节点经过的次数
findH(en); //计算反向距离表H
if(H[st]==(int)INF) return -1;//en不能到达st
p.s=st;p.G=0;p.F=H[st];
q.push(p);
while(!q.empty()){
p=q.top();q.pop();
k[p.s]++;
if(k[p.s]>K) continue;
if(p.s==en&&k[p.s]==K) return p.F;
int m=map[p.s].size();
for(int i=0;i<m;i++){
int j=map[p.s][i].v;
if(H[j]!=(int)INF){
tp.G=p.G+map[p.s][i].w;
tp.F=H[j]+tp.G;
tp.s=j;
q.push(tp);
}
}
}
return -1;
}
int main(){
int n,m,S,T,K,a,b,t;
node p;
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++){
map[i].clear();
tmap[i].clear();
H[i]=INF;
}
while(m--){
scanf("%d%d%d",&a,&b,&t);
p.v=b;p.w=t;map[a].push_back(p);
p.v=a;tmap[b].push_back(p);
}
scanf("%d%d%d",&S,&T,&K);
if(S==T) K++;
printf("%d\n",Astar(S,T,K));
return 0;
}
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1100;
const int M=100050;
struct node{
int v,w,next;
};
node edge1[M];
int head[N];
node edge2[M];
int rhead[N];
int H[N];
struct PATH{
int F,G,s;
friend bool operator < (PATH a,PATH b){
return a.F>b.F;
}
};
void spfa(int s){
queue<int>q;
int vis[N]={0};
q.push(s);vis[s]=1;H[s]=0;
while(!q.empty()){
s=q.front();
q.pop();
vis[s]=0;
for(int i=rhead[s];~i;i=edge2[i].next){
int j=edge2[i].v;
if(H[j]>edge2[i].w+H[s]){
H[j]=edge2[i].w+H[s];
if(!vis[j]){
vis[j]=1,q.push(j);
}
}
}
}
}
int Astar(int st,int en,int K){
spfa(en);
if(H[st]==inf){
return -1;
}
priority_queue<PATH> q;
PATH p,tp;
int k[N]={0};
p.s=st;p.G=0;p.F=H[st];
q.push(p);
while(!q.empty()){
p=q.top();
q.pop();
k[p.s]++;
if(k[p.s]>K) continue;
if(p.s==en&&k[p.s]==K) return p.F;
for(int i=head[p.s];~i;i=edge1[i].next){
int j=edge1[i].v;
if(H[j]!=inf){
tp.G=p.G+edge1[i].w;
tp.F=H[j]+tp.G;
tp.s=j;
q.push(tp);
}
}
}
return -1;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
head[i]=-1;
rhead[i]=-1;
H[i]=inf;
}
int a,b,t,cnt=0;
while(m--){
scanf("%d%d%d",&a,&b,&t);
edge1[cnt].v=b;
edge1[cnt].w=t;
edge1[cnt].next=head[a];
head[a]=cnt;
edge2[cnt].v=a;
edge2[cnt].w=t;
edge2[cnt].next=rhead[b];
rhead[b]=cnt;
cnt++;
}
int S,T,K;
scanf("%d%d%d",&S,&T,&K);
if(S==T){
K++;
}
printf("%d\n",Astar(S,T,K));
return 0;
}