从一个点s到t的第k短的路径。
我以前只会打从一个点到另一个点的最短路径。
后来去看了看k短路径的求法。
设估价函数 g[i]=f[i]+p[i] , f[i] 表示i到t的最短路径的长度, p[i] 表示s到i目前走得距离。
首先,我们把原图的边全部反向连边。然后求出所有的点到t的最短路径。
然后,我们把s丢进堆里面,堆的判断大小条件以g为第一关键字,f为第二关键字。
每次取出堆顶a,把它弹出去,如果弹出去的是t,那么cnt++(表示找到了第cnt短路),如果cnt=k,那么就退出 。
把与a向连的点,计入f和g,丢进堆里面。
这样就可以了。
POJ2249
#include
#include
#include
#include
#include
#include
#define fo(i,a,b) for(i=a;i<=b;i++)
#define rep(i,a) for(i=first[a];i;i=next[i])
#define rep1(i,a) for(i=first1[a];i;i=next1[i])
using namespace std;
const int maxn=200007;
int i,j,k,l,n,m,ans,x,y,z,ss,tt;
int first[maxn],last[maxn],next[maxn],chang[maxn],num;
int first1[maxn],last1[maxn],next1[maxn],chang1[maxn],num1;
int d[maxn],data[maxn*10];
bool bz[maxn];
struct node{
int a,g,f;
bool friend operator <(node x,node y){
if(x.g==y.g)return !(x.freturn !(x.g t;
void add(int x,int y,int z){
last[++num]=y,next[num]=first[x],first[x]=num,chang[num]=z;
}
void add1(int x,int y,int z){
last1[++num1]=y,next1[num1]=first1[x],first1[x]=num1,chang1[num1]=z;
}
void spfa(int x){
int head=0,tail=1,i,now;
memset(d,127,sizeof(d));
data[1]=x,d[x]=0,bz[x]=1;
while(headif(d[now]+chang1[i]if(!bz[last1[i]]){
bz[last1[i]]=1;
data[++tail]=last1[i];
}
}
}
bz[now]=0;
}
}
void a_star(){
int i;
if(ss==tt)k++;
if(d[ss]==2139062143)return;
o.a=ss,o.f=0,o.g=d[ss];t.push(o);
while(!t.empty()){
p=t.top();
t.pop();
if(p.a==tt)k--;
if(!k){
ans=p.f;
return;
}
rep(i,p.a){
o.a=last[i];
o.f=p.f+chang[i];
o.g=o.f+d[last[i]];
t.push(o);
}
}
}
int main(){
scanf("%d%d",&n,&m);
fo(i,1,m){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add1(y,x,z);
}
scanf("%d%d%d",&ss,&tt,&k);
ans=-1;
spfa(tt);
a_star();
printf("%d\n",ans);
}