k短路

扫码查看

问题模型

给定一个有\(n\)个结点, \(m\)条边的有向图,求从\(s\)\(t\)的所有不同路径中的第\(k\)短路径的长度。

算法分析

\(A*\)算法\(+Dijkstra\)

先以\(t\)为源点跑一边\(Dijkstra\),困难的地方其实是在\(A\)_\(star()\)函数的理解,见一下注释:

struct node
{
    int id,g,f;
//g为目前的点到源点的距离,f是一个估计函数(简而言之就是一个估计值)
    bool operator < (node tmp) const
    {
        if(f==tmp.f) return g>tmp.g;
        return f>tmp.f;
    }
};
priority_queue<node> q;
int cnt[N];//计数器优化
void A_star()
{
    if(s==t) ++k;
    q.push((node){s,0,d[s]});
    int nw,dis;
    while(!q.empty())
    {
        nw=q.top().id,
        dis=q.top().g;
        q.pop();
        ++cnt[nw];
        if(cnt[nw]>k) continue;//只需扩展前k小的
        if(nw==t)
        {
            if(cnt[t]==k)
            {
                printf("%d\n",dis);
                return;
            }
        }
        for(int i=h2[nw];i;i=e[i].nx)
            q.push((node){e[i].v,dis+e[i].w,dis+e[i].w+d[e[i].v]});
    }
    puts("-1");
}

例题[POJ2449] Remmarguts' Date代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
using namespace std;

const int N=1500,M=250000;
int n,m,s,t,k;
struct edge
{
    int v,w,nx;
}e[M];
int ne,h1[N],h2[N];

void Build1(int u,int v,int w)
{
    ++ne,e[ne]=(edge){v,w,h1[u]},h1[u]=ne;
}

void Build2(int u,int v,int w)
{
    ++ne,e[ne]=(edge){v,w,h2[u]},h2[u]=ne;
}

void Read()
{
    scanf("%d%d",&n,&m);
    int u,v,w;
    for(int i=1;i<=m;++i)
    {
        scanf("%d%d%d",&u,&v,&w);
        Build1(v,u,w),
        Build2(u,v,w);
    }
    scanf("%d%d%d",&s,&t,&k);
}

const int INF=99999999;
typedef pair<int,int> pr;
priority_queue<pr,vector<pr>,greater<pr> > Q;//坑了我一个下午,无奈……
int d[N]; bool v[N];
void Dijkstra()
{
    for(int i=1;i<=n;++i) d[i]=INF;
    d[t]=0;
    Q.push(make_pair(0,t));
    int nw;
    while(!Q.empty())
    {
        nw=Q.top().second; Q.pop();
        if(v[nw]) continue;
        v[nw]=1;
        for(int i=h1[nw];i;i=e[i].nx)
            if(d[e[i].v]>d[nw]+e[i].w)
            {
                d[e[i].v]=d[nw]+e[i].w;
                Q.push(make_pair(d[e[i].v],e[i].v));
            }
    }
}

struct node
{
    int id,g,f;
    bool operator < (node tmp) const
    {
        if(f==tmp.f) return g>tmp.g;
        return f>tmp.f;
    }
};
priority_queue<node> q;
int cnt[N];
void A_star()
{
    if(s==t) ++k;
    q.push((node){s,0,d[s]});
    int nw,dis;
    while(!q.empty())
    {
        nw=q.top().id,
        dis=q.top().g;
        q.pop();
        ++cnt[nw];
        if(cnt[nw]>k) continue;
        if(nw==t)
        {
            if(cnt[t]==k)
            {
                printf("%d\n",dis);
                return;
            }
        }
        for(int i=h2[nw];i;i=e[i].nx)
            q.push((node){e[i].v,dis+e[i].w,dis+e[i].w+d[e[i].v]});
    }
    puts("-1");
}

int main()
{
    Read(),Dijkstra(),A_star();
    return 0;
}
12-21 00:20
查看更多