POJ 2449 Remmarguts' Date

POJ 2449 Remmarguts` Date

K短路,A*算法+dijkstra

传送门:POJ


题意

给你个图,给起点终点,k。求第k短路。注意必须走路,不能不走。


思路

初学A*算法。膜大佬

说说自己的理解吧。概念什么的就不说了。对比着dijkstra算法说:

  1. 建图的时候建两个,一个正向建,一个反向建,反向就是一条路起点终点反过来,距离不变。

  2. 先用dijkstra跑一遍反向的图,求出估值函数hx——终点到各点距离,A*算法更新需要用。

  3. dij里面有个d数组,记录距离的,而A*算法没有,因为求得不是最短路,没法更新d数组,所以距离保存在优先队列里面。

  4. 需要一个数组,记录A*中某点的出队次数,出队一次代表以它为更新点更新了别人一次,终点t更新了k次后就是k短路。可以终止更新。

  5. A*队列里这样封装数据:

    int point;//当前点
    int g;//fx,表示当前点到终点的距离
    int dis;//表示起点到当前点的距离
    bool operator <(const Queue &a) const
    {
        return g+dis>a.g+a.dis;
    }
  6. 每次取队首元素,就是总距离最小的元素,对所连边更新。

  7. 如果不算反向图的距离,感觉就是dijkstra。。。每次选最短的路更新周围的点。。


代码

注意一下,如果起点s==终点t,那么k需要+1,因为这种情况有一条路是什么都不走,这是“第一短路”,而题目要求必须走路

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;

const int MAXN=200007;
const int oo=1000000007;
typedef long long LL;
struct Graph{
    int next;
    int to;
    int cost;
}G_inv[MAXN],G[MAXN];
int head[MAXN],head_inv[MAXN];
struct Queue{
    int point;//当前点
    int g;//fx,表示当前点到终点的距离
    int dis;//表示起点到当前点的距离
    Queue(){}
    Queue(int _point,int _dis,int _g){ point=_point;dis=_dis;g=_g; }
    bool operator <(const Queue &a) const
    {
        return g+dis>a.g+a.dis;
    }
};

int d_inv[MAXN];
int dijkstra(int n,int m,int s,int t)//点数,边数,起点,终点
{
    memset(d_inv,0x3f,sizeof(d_inv));
    priority_queue<Queue> que;
    d_inv[s]=0;
    while(!que.empty()) que.pop();
    que.push(Queue(s,0,0));
    while(!que.empty())
    {
        Queue temp=que.top();
        que.pop();
        if(temp.dis>d_inv[temp.point]) continue;
        int pn=temp.point;
        if(d_inv[pn]<temp.dis) continue;
        for(int i=head_inv[pn];i!=-1;i=G_inv[i].next)
        {
            int dis1,to1;
            dis1=temp.dis+G_inv[i].cost;
            to1=G_inv[i].to;
            if(dis1<d_inv[to1])
            {
                d_inv[to1]=dis1;
                que.push(Queue(to1,dis1,0));
            }
        }
    }
    return d_inv[t];
}
int refresh[MAXN];
int astar(int s,int t,int k)
{
    priority_queue<Queue> que;
    memset(refresh,0,sizeof(refresh));
    while(!que.empty()) que.pop();

    que.push(Queue(s,0,d_inv[s]));
    while(!que.empty())
    {
        Queue temp=que.top();
        que.pop();
        int po=temp.point;
        refresh[po]++;
        if(refresh[po]>k) continue;
        if(refresh[t]==k) return temp.dis;
        for(int i=head[po];~i;i=G[i].next)
        {
            int v=G[i].to;
            int disn=G[i].cost+temp.dis;
            que.push(Queue(v,disn,d_inv[v]));
        }
    }
    return -1;//没有k短路,输出-1
}
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)==2)
    {
        memset(head,-1,sizeof(head));
        memset(G,0,sizeof(G));
        memset(head_inv,-1,sizeof(head_inv));
        memset(G_inv,0,sizeof(G_inv));
        for(int i=0;i<m;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            G[i].to=b;G[i].cost=c;G[i].next=head[a];head[a]=i;
            swap(a,b);
            G_inv[i].to=b;G_inv[i].cost=c;G_inv[i].next=head_inv[a];head_inv[a]=i;
        }
        int s,t,k;
        scanf("%d%d%d",&s,&t,&k);
        dijkstra(n,m,t,s);
        if(s==t) k++;
        printf("%d\n",astar(s,t,k));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值