POJ 2449 Remmarguts' Date --K短路

题意就是要求第K短的路的长度(S->T)。

对于K短路,朴素想法是bfs,使用优先队列从源点s进行bfs,当第K次遍历到T的时候,就是K短路的长度。

但是这种方法效率太低,会扩展出很多状态,所以考虑用启发式搜索A*算法。

估价函数 = 当前值 + 当前位置到终点的距离,即F(p) = G(p) + H(p)。 

G(p): 当前从S到p所走的路径距离

H(p): 当前点p到终点T的最短路径距离   ---可以先将整个图边方向取反然后以T为源点求个最短路,用SPFA提速

F(p): 从S按照当前路径走到p然后走到T一共至少走多远

所以我们结合SPFA+A*可以解决。

注意:当S==T时,需要计算第K+1短路,因为从S->T这条长度为0的路径不能算在内。

还有,SPFA处判了一下负环。SPFA算法中,如果某个点出队次数大于n,说明此处存在负环。

代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

#include <queue>

#include <functional>

#define Mod 1000000007

using namespace std;

#define N 1007



struct node

{

    int v;

    int g,f; //f = g+h

    bool operator < (const node &a)const

    {

        if(a.f == f)

            return a.g < g;

        return a.f < f;

    }

};



struct Edge

{

    int v,w,next;

}G[100*N],G2[100*N];



int head[100*N],head2[100*N];

int vis[N],dis[N];

int out[N];

int n,m,K,S,T,tot,tot2;



void addedge(Edge *G,int& tot,int *head,int u,int v,int w)

{

    G[tot].v = v;

    G[tot].w = w;

    G[tot].next = head[u];

    head[u] = tot++;

}



int SPFA(int s,int head[N],Edge G[N],int dis[N])

{

    int i;

    queue<int> que;

    for(i=0;i<=n;i++)

        dis[i] = Mod;

    memset(vis,0,sizeof(vis));

    memset(out,0,sizeof(out));

    que.push(s);

    vis[s] = 1;

    dis[s] = 0;

    while(!que.empty())

    {

        int now = que.front();

        que.pop();

        vis[now] = 0;

        out[now]++;

        if(out[now] > n)

            return 0;

        for(int k=head[now];k!=-1;k=G[k].next)

        {

            if(dis[G[k].v] > dis[now] + G[k].w)

            {

                dis[G[k].v] = dis[now] + G[k].w;

                if(!vis[G[k].v])

                {

                    vis[G[k].v] = 1;

                    que.push(G[k].v);

                }

            }

        }

    }

    return 1;

}



int A_Star(int head[N],Edge G[N],int dis[N])

{

    node tmp,now;

    int cnt = 0;

    priority_queue<node> que;

    if(S == T)

        K++;

    if(dis[S] == Mod)

        return -1;

    tmp.v = S;

    tmp.g = 0;

    tmp.f = tmp.g+dis[S];

    que.push(tmp);

    while(!que.empty())

    {

        tmp = que.top();

        que.pop();

        if(tmp.v == T)

            cnt++;

        if(cnt == K)

            return tmp.g;

        for(int i=head[tmp.v];i!=-1;i=G[i].next)

        {

            now.v = G[i].v;

            now.g = tmp.g + G[i].w;

            now.f = now.g + dis[now.v];

            que.push(now);

        }

    }

    return -1;

}



int main()

{

    int i,j,u,v,w;

    while(scanf("%d%d",&n,&m)!=EOF)

    {

        memset(head,-1,sizeof(head));

        memset(head2,-1,sizeof(head2));

        tot = tot2 = 1;

        for(i=0;i<m;i++)

        {

            scanf("%d%d%d",&u,&v,&w);

            addedge(G,tot,head,u,v,w);   //原图

            addedge(G2,tot2,head2,v,u,w);   //反图

        }

        scanf("%d%d%d",&S,&T,&K);

        if(SPFA(T,head2,G2,dis))

        {

            int k_len = A_Star(head,G,dis);

            printf("%d\n",k_len);

        }

        else

            puts("-1");

    }

    return 0;

}
View Code

 

你可能感兴趣的:(Date)