题意:找第K短路的值
思路:A*,bfs找K短路的时候加上估计函数(距离下界),而且要满足:cost(u,v)+h*(u)-h*(v)>=0
因为这是bfs'需要的下界函数,不是任何下界都可以,不像IDA*,这里的下界必须让每个bfs的节点保持原样的大小关系
而IDDFA中的A*下界函数就不需要这个性质了,只要是下界即可。
显然这个具体问题的天然的估计函数就是从此点到目标点的最短路。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int M =1e5+100; const int N =1e3+10; const int inf = 0x3f3f3f3f ; struct Edge { int v; int w; int next; }es1[M],es2[M]; int head1[N],head2[N]; int n,m; int s,g,k; bool vis[N]; int dis[N]; void spfa() { memset(vis,0,sizeof(vis)); dis[g]=0; queue<int >q; q.push(g); vis[g]=true; while(!q.empty()) { int cur=q.front(); q.pop(); vis[cur]=false; for(int i=head2[cur];~i;i=es2[i].next) { int v=es2[i].v,w=es2[i].w; if(dis[v]>dis[cur]+w) { dis[v]=dis[cur]+w; if(vis[v]) continue; vis[v]=true; q.push(v); } } } } struct node { int u; int g,f; bool operator < (const node &a) const { return a.f<f; //按f最小堆 } }; int A_star() { int cnt=0; priority_queue<node> que; if(dis[s]==inf) return -1; //剪枝 node st; st.g=0,st.f=dis[s],st.u=s; que.push(st); while(!que.empty()) { node cur=que.top(); que.pop(); if(cur.u==g) cnt++; if(cnt==k) return cur.g; for(int i=head1[cur.u];~i;i=es1[i].next) { int v=es1[i].v,w=es1[i].w; node nxt; nxt.u=v,nxt.g=cur.g+w,nxt.f=nxt.g+dis[v]; que.push(nxt); } } return -1; } void ini() { fill(dis,dis+1005,inf); memset(head1,-1,sizeof(head1)); memset(head2,-1,sizeof(head2)); } int main() { while(~scanf("%d%d",&n,&m)) { ini(); for(int i=1;i<=m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); es1[i].v = v,es1[i].w=w,es1[i].next=head1[u]; head1[u]=i; es2[i].v=u,es2[i].w=w,es2[i].next=head2[v]; head2[v]=i; } scanf("%d%d%d",&s,&g,&k); if(s==g) k++; //易错,当s和g重合时,没经过其他路不算一种方法 spfa(); printf("%d\n",A_star()); } return 0; }