第k短路

来源:互联网 发布:君子去仁 恶乎成名 编辑:程序博客网 时间:2024/06/05 08:43

这可爱的问题,呵呵
启发式搜索的一大旗舰问题
要弄懂它,你先去复习一下可爱的spfa吧…
当然,不怕浪费时间floyd也行
总之能求出单源最短路就行


↓↓复习完的看这里(☄⊙ω⊙)☄↓↓

题目顾名思义,就是求第k短的路径
我们的启发函数该怎么写呢
这是一个不太深奥的问题
f=g+h;
g我们就当作到当前点已经过的路程
h就依然延续以前的想法取当前点到终点的最短距离
那么我们就可以用spfa预处理一个h[i]数组记录终点到第i个点的距离
那么说明一下大概思路
用启发式搜索搜索最短路,但当到达终点时不停止
直到第k次到达终点,就是要求的第k短路
注意: 当起点与终点相同时,由于长度为0没有意义所以第k+1短路为所求


示范:以1节点为起点,n节点为终点(我没判负环φ(゜▽゜*)♪ )

#include <cstdio>#include <queue>using namespace std;typedef long long ll;const ll inf=1000000000000000000ll;struct edge1{    int to,next;    ll len;}da1[100001],da2[100001];struct edge2{    int to;    ll g,f;    bool operator <(const edge2 &s)const    {        if(f==s.f)            return g>s.g;        return f>s.f;    }    edge2(){}};int head1[10001],head2[10001],cnt[10001];ll h[10001];bool v[10001];int n,r,k,idx,ide;queue <int> q;priority_queue <edge2> Q;void add1(int x,int y,ll z){    da1[++idx].to=y;    da1[idx].len=z;    da1[idx].next=head1[x];    head1[x]=idx;    return ;}void add2(int x,int y,ll z){    da2[++ide].to=y;    da2[ide].len=z;    da2[ide].next=head2[x];    head2[x]=ide;    return ;}void spfa(){    for(int i=0;i<n;i++)        h[i]=inf;    q.push(n);    v[n]=true;    cnt[n]++;    while(!q.empty())    {        int tmp=q.front();        q.pop();        v[tmp]=false;        for(int i=head2[tmp];i;i=da2[i].next)        {            int tp=da2[i].to;            if(h[tp]>h[tmp]+da2[i].len)            {                h[tp]=h[tmp]+da2[i].len;                if(!v[tp])                {                    q.push(tp);                    v[tp]=true;                }                if(++cnt[tp]>n) return ;            }        }    }    return ;}ll A_s(){    edge2 tmp;    if(n==1)        k++;    int cnt=0,l;    tmp.to=1;    tmp.g=0;    tmp.f=tmp.g+h[tmp.to];    Q.push(tmp);    while(!Q.empty())    {        tmp=Q.top();        Q.pop();        if(tmp.to==n)        {            int tp=tmp.g;            if(tp!=l)            {                l=tp;                cnt++;            }        }        if(cnt==k)            return tmp.g;        for(int i=head1[tmp.to];i;i=da1[i].next)        {            edge2 tp;            tp.to=da1[i].to;            tp.g=tmp.g+da1[i].len;            tp.f=tp.g+h[tp.to];            Q.push(tp);        }    }    return -1;}int main(){    scanf("%d%d%d",&n,&r,&k);    for(int i=1;i<=r;i++)    {        int a,b;        ll c;        scanf("%d%d%lld",&a,&b,&c);        add1(a,b,c);        add2(b,a,c);    }    spfa();    printf("%lld",A_s());    return 0;}
0 0
原创粉丝点击