A*與K短路
阿新 • • 發佈:2019-01-10
A*演算法
一般的搜尋有兩種:BFS或DFS。這兩種搜尋都有一個特點,就是搜尋順序與每個節點與起點的距離有關,但是,這樣搜尋的節點很多是沒有必要的,在現實中,我們在走下一步時,還要考慮下一步到終點的距離, ∗
K短路
求最短路很簡單,求次短路也很簡單(只要把最短路上的某一條邊去掉後再重新刷最短路,所有的值中最小的就是次短路),但是要求k短路好像就有點麻煩了。
設想一下,如果A*的估價函式完全與真實距離相等,那麼每一次搜尋到終點都是當前最優的,所以第k次搜尋到終點的距離就是k短路了。估價函式完全可以預處理,只要把所有的邊倒過來,然後從終點開始刷最短路,從終點到每個點的距離就是那個點的估價函式。
模板題:POJ 2449
程式碼:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxn 1006
#define maxe 100006
using namespace std;
inline char nc(){
static char buf[100000],*i=buf,*j=buf;
return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;
}
inline int _read(){
char ch=nc();int sum=0;
while(!(ch>='0'&&ch<='9'))ch=nc();
while (ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
return sum;
}
int n,e,ans,S,T,K,hed,tal,tot[2],que[maxn],dis[maxn],lnk[2][maxn],nxt[2][maxe],son[2][maxe],w[2][maxe];
bool vis[maxn];
struct data{
int x,g;
data(int X,int G){x=X,g=G;}
bool operator <(const data&b)const{
return g+dis[x]>b.g+dis[b.x];
}
};
priority_queue<data> heap;
void add(int p,int x,int y,int z){
nxt[p][++tot[p]]=lnk[p][x];son[p][tot[p]]=y;w[p][tot[p]]=z;lnk[p][x]=tot[p];
}
void spfa(){
memset(dis,63,sizeof(dis));memset(vis,0,sizeof(vis));
hed=0;que[tal=1]=T;vis[T]=1;dis[T]=0;
while(hed!=tal){
hed=(hed+1)%maxn;vis[que[hed]]=0;
for(int j=lnk[1][que[hed]];j;j=nxt[1][j]) if(dis[son[1][j]]>dis[que[hed]]+w[1][j]){
dis[son[1][j]]=dis[que[hed]]+w[1][j];
if(!vis[son[1][j]]){
vis[son[1][j]]=1;
que[tal=(tal+1)%maxn]=son[1][j];
if(dis[que[tal]]<dis[que[(hed+1)%maxn]])swap(que[tal],que[(hed+1)%maxn]);
}
}
}
}
void A_star(){
while(!heap.empty())heap.pop();
heap.push(data(S,0));
while(!heap.empty()){
data x=heap.top();heap.pop();
if(x.x==T&&(!(--K))){
printf("%d",x.g);
return;
}
for(int j=lnk[0][x.x];j;j=nxt[0][j])heap.push(data(son[0][j],x.g+w[0][j]));
}
}
int main(){
freopen("dist.in","r",stdin);
freopen("dist.out","w",stdout);
n=_read();e=_read();
for(int i=1,x,y,z;i<=e;i++)x=_read(),y=_read(),z=_read(),add(0,x,y,z),add(1,y,x,z);
S=_read();T=_read();K=_read();if(S==T)K++;
spfa();A_star();
if(K)printf("-1");
return 0;
}