第k短路问题

思路

A*搜索(bfs剪枝),评估函数由dijkstra给出,即从终点跑一遍dijkstra.然后从起点跑bfs,bfs设一个优先队列(按f值从小到大取出),每次入点时算一下f值,f=g+h,g为起点到当前点的实际距离,h为当前点到终点的估计距离,这里用之前跑的dijkstra来充当h.即f(i)=g(i)+d[i].当这个bfs第i次抵达终点算出来的就是第k短路.需要注意的是如果是有向图从终点跑的话需要把边反向,不然会卡死.

代码

typedef pair<int,int> P;
struct edge
{
    int to,cost;
    edge (){}
    edge (int x,int y){to=x,cost=y;}
};
vector<edge> es[MAX+1]; 
int d[MAX+1];
int n,m;

void add(int s,int t,int c) //这里写的是无向图,有向图记得dijkstra要跑反边 
{
    es[s].push_back(edge(t,c));
    es[t].push_back(edge(s,c));
    return ;
}
 
void dijkstra(int s) //从终点开始跑 
{
    priority_queue<P,vector<P>,greater<P> > que;
    fill(d+1,d+n+1,INF); //点编号从1开始 
    d[s]=0;
    que.push(P(0,s)); //first为当前最短距离,seocnd为点 
    while(que.size())
    {
        P p=que.top();que.pop();
        int x=p.second;
        if(d[x]<p.first) continue;
        for(int i=0;i<es[x].size();i++)
        {
            edge e=es[x][i];
            if(d[e.to]>d[x]+e.cost)
            {
                d[e.to]=d[x]+e.cost;
                que.push(P(d[e.to],e.to));
            }
        }
    }
}

int bfs(int s,int k) //起点为s,求第k短路 
{
    priority_queue<P,vector<P>,greater<P> > que;
    que.push(P(0+d[s],s)); //first是f值,second是点 
    int cnt=k;
    while(que.size())
    {
        P p=que.top();que.pop();
        int x=p.second;
        if(x==n)
        {
            cnt--;
            if(!cnt) return p.first-d[x];
        }
        for(int i=0;i<es[x].size();i++)
        {
            edge e=es[x][i];
            que.push(P(p.first-d[x]+e.cost+d[e.to],e.to));
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/VBEL/p/10714884.html
今日推荐