第K短路模板【POJ2449 / 洛谷2483 / BZOJ1975 / HDU6181】

1.到底如何求k短路的?

      我们考虑,要求k短路,要先求出最短路/次短路/第三短路……/第(k-1)短路,然后访问到第k短路。

      接下来的方法就是如此操作的。

2.f(x)的意义?

      我们得到的f(x)更小,优先访问这个f(x)的点。

      我们可以定义一组数{p,g,h},p是某一个点,g是估价,h是实际,那么g+h更小的点p会优先访问。

      为什么呢?因为假设我们求出了w短路,接下来要求(w+1)短路,就要求最小的另一条路径。

      应该易理解。

3.为什么选择最短路来估价?

      很简单的选择,我们既然要求最短了,当然是找最短路。

      事实上这不是我们的初衷,但是有了“先求(k-1)短路”的概念后,这么理解也可以了。

4.实现

      实现是比较简单的。

      如何预处理出g(x)呢?显然,将所有边反向,然后求end到所有点的单源最短路径就好了。

      接下来的启发式搜索可以简单解决。

事实上,就是在暴力搜索的基础上增加了启发式搜索:往一个最优的点的地方走。

另外还是要专来一篇这题blog的QAQ

关于上题目的程序:

86ms

#include<iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;
const int N=100000+10;
const int inf=0x3f3f3f3f;
struct edge
{
    int u,v,w,next;
}e[N<<1];
int head[N<<1],head1[N<<1],dis[N<<1],vis[N<<1],cnt[N<<1];
int num;
int n,m;
int s,t,k;
struct node
{
    int g,h;
    int to;
    bool operator<(node a)const
    {
        return a.h+a.g<h+g;
    }
};
void init()
{
    num=0;
    memset(head1,-1,sizeof(head1));
    memset(head,-1,sizeof(head));
}
void addegde(int u,int v,int w)
{
    e[num].v=v;
    e[num].w=w;
    e[num].next=head[u];
    head[u]=num++;
    e[num].v=u;
    e[num].w=w;
    e[num].next=head1[v];
    head1[v]=num++;
}
void spfa()
{
    memset(vis,0,sizeof(vis));
    memset(dis,inf,sizeof(dis));
    dis[t]=0;
    vis[t]=1;
    queue<int>q;
    q.push(t);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head1[u];i!=-1;i=e[i].next)
        {
            int v=e[i].v;
            if(dis[v]>dis[u]+e[i].w)
            {
                dis[v]=dis[u]+e[i].w;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
}
int AA()
{
    memset(cnt,0,sizeof(cnt));
    priority_queue<node>Q;
    node p,q;
    p.g=0;
    p.to=s;
    p.h=dis[s];
    Q.push(p);
    while(!Q.empty())
    {
        q=Q.top();
        Q.pop();
        cnt[q.to]++;
        if(cnt[q.to]>k)
            continue;
        if(cnt[t]==k)
            return q.g;
        for(int i=head[q.to];i!=-1;i=e[i].next)
        {
            int v=e[i].v;
            p.to=v;
            p.g=q.g+e[i].w;
            p.h=dis[v];
            Q.push(p);
        }
    }
    return -1;
}
int main()
{
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        scanf("%d%d",&s,&t);
        init();
        for(int i=0;i<m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            addegde(u,v,w);
        }
        
        spfa();
        if(s==t)k++;
        //cout<<dis[s]<<endl;
        int ans=AA();
        printf("%d
",ans);
    }
    return 0;
}
SPFA+A*
原文地址:https://www.cnblogs.com/Roni-i/p/9441194.html