求图的第K短路(A*算法与最短路的应用)

来源:互联网 发布:俄罗斯姑娘知乎 编辑:程序博客网 时间:2024/05/29 17:51

前言:最短路算法是我们非常熟悉的了。Dijkstra,SPFA等单源最短路算法是我们在竞赛中常用的算法。那么,假如题目要求的不是最短的呢?

Question(1):给定一个图,求次短路。

对于次短路,很容易想到在比较的时候进行处理。

设dis(u)为原点s到u的最短路径,u为当前节点,v和u有边相连。

x = dis[v] + f[u][v];

则对于最短路:if(dis[u] > x) dis[u] = x;

而对于次短路:

if(dis[u]>x) dis2[u]=dis[u],dis[u]=x;

else if(dis2[u]>x) dis2[u]=x;

所以,对于次短路,只需加多一个数组即可。


那么,K短路呢?

Question(2):给定一个图,求第K短路。

对于这个问题,可以用A*算法+Dijkstra解决。


先了解一下A*算法:

A*算法是一种典型的启发式搜索算法。定义:

h*(s)为状态s到目标的距离

h(s)为估价函数,状态s到目标距离的下界,即h(s)<=h*(s)

g(s)为到达状态s所需的代价

f(s)为s的启发函数。有f(s) = h(s) + g(s)。


那么,对于本题:h(s)就是源点到s的距离,g(s)为到终点t的实际距离。

如果能求出g,那么,当A*搜索了终点k次后,当前的h就为答案。

求函数g的方法:因为g(s)为到终点t的实际距离,所以,可以把原图的边反向后,把终点改成源点,跑一次Dijkstra,算出每一个点u到t的距离,就是所求的g。

附上求K短路的模板:POJ2449

#include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cmath>#include <cstdlib>#include <stack>#include <queue>#include <map>#include <set>using namespace std;#define Maxn 10010#define INF 1000000000struct node{int to,val;node() {}node(int a,int b){to = a; val = b;}};vector<node> adj[Maxn],_adj[Maxn];int n,m,k;bool vis[Maxn];int dis[Maxn];void AddEdge(int x,int y,int val){adj[x].push_back(node(y,val));_adj[y].push_back(node(x,val));//把图反向}void Dijkstra(int s,int t){priority_queue<int , vector<int> , greater<int> > q;while(!q.empty()) q.pop();for(int i=1;i<=n;i++) vis[i] = false,dis[i] = INF;vis[t] = true; dis[t] = 0; q.push(t);int u,len;while(!q.empty()){u = q.top();  q.pop();len = _adj[u].size();for(int i=0;i<len;i++){node v = _adj[u][i];if(dis[v.to] > dis[u] + v.val){dis[v.to] = dis[u] + v.val;if(!vis[v.to]){q.push(v.to);vis[v.to] = true;}}}vis[u] = false;}}struct Anode{int h,g,id;Anode(int a,int b,int c) {h=a; g=b; id=c;}bool operator < (Anode a) const{return h+g > a.h+a.g;}};priority_queue<Anode> Q;int Astar(int s,int t)//A*算法过程{while(!Q.empty()) Q.pop();Q.push(Anode(0,dis[s],s));int len,num;num = 0;while(!Q.empty()){Anode u = Q.top(); Q.pop();if(u.id==t) ++num;if(num>=k) return u.h;len = adj[u.id].size();for(int i=0;i<len;i++){node v = adj[u.id][i];Q.push(Anode(u.h+v.val,dis[v.to],v.to));}}return -1;//不能连通或者没有第K短路}int main(){while(scanf("%d%d",&n,&m)!=-1){for(int i=0;i<Maxn;i++) adj[i].clear(),_adj[i].clear();int x,y,v,s,t;for(int i=1;i<=m;i++){scanf("%d%d%d",&x,&y,&v);AddEdge(x,y,v);}scanf("%d%d%d",&s,&t,&k);if(s==t) k++;Dijkstra(s,t);printf("%d\n",Astar(s,t));}return 0;}


1 0