POJ 2449 第k长的最短路径

来源:互联网 发布:不用网络的导航 编辑:程序博客网 时间:2024/06/05 08:36

迪杰斯特拉+A*算法

f(i) = g(i) + h(i)

优先队列每次让队列中f最小的值出队

若t第n次从队列出来,则为从s到t的第K条最短路径

#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;


struct Edge
{
    int to;
    int w;
    int next;
};


Edge edge[100100];
Edge edge2[100100];


struct Node
{
    int f;
    int g;
    int v;
    bool operator < (const Node &b) const
    {
        return b.f < f;
    }
};


int head[1005];
int head2[1005];
int dis[1005];
int visit[1005];
int cnt[1005];


const int MAX = 0x7fffffff;


void dijkstra(int start,int n)
{
    dis[start] = 0;
    for(int i = 1;i<=n;i++)
    {
        int temp = MAX;
        int record = 0;
        for(int j = 1;j<=n;j++)
        {
            if(visit[j]==false&&dis[j]<temp)
            {
                temp = dis[j];
                record = j;
            }
        }
        visit[record] = true;
        for(int i = head2[record];i!=0;i=edge2[i].next)
        {
            int k = edge2[i].to;
            int w = edge2[i].w;
            if(visit[k]==false&&dis[k]>dis[record]+w)
            {
                dis[k] = dis[record]+w;
            }
        }
    }
}


int AStar(int start,int end,int k)
{
    priority_queue <Node> que;
    if(dis[start]==MAX)
    {
        return -1;
    }
    Node t;
    t.f = dis[start];t.g = 0;t.v = start;
    que.push(t);
    while(!que.empty())
    {
        Node t = que.top();
        que.pop();
        cnt[t.v]++;
        if(cnt[end]==k)
            return t.f;
        for(int i = head[t.v];i!=0;i=edge[i].next)
        {
            Node temp;
            temp.v = edge[i].to;
            temp.g = t.g+edge[i].w;
            temp.f = temp.g+dis[temp.v];
            que.push(temp);
        }
    }
    return -1;


}


int main()
{
    int n,m,u,v,w;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        for(int i = 0;i<1005;i++)
        {
            head[i] = head2[i] = cnt[i]=0;
            visit[i] = false;
            dis[i] = MAX;
        }
        for(int i = 1;i<=m;i++)
        {
            scanf("%d %d %d",&u,&v,&w);
            edge[i].to = v;
            edge[i].w = w;
            edge[i].next = head[u];
            head[u] = i;
            edge2[i].to = u;
            edge2[i].w = w;
            edge2[i].next = head2[v];
            head2[v] = i;
        }
        scanf("%d %d %d",&u,&v,&w);
        dijkstra(v,n);
        if(u==v)
            w++;
        int ans = AStar(u,v,w);
        printf("%d\n",ans);
    }
    return 0;
}