POJ 2449 Remmarguts' Date(A* - 第K短路)

16 篇文章 0 订阅
2 篇文章 0 订阅

题意:找第K短路的值

思路:A*,bfs找K短路的时候加上估计函数(距离下界),而且要满足:cost(u,v)+h*(u)-h*(v)>=0

因为这是bfs'需要的下界函数,不是任何下界都可以,不像IDA*,这里的下界必须让每个bfs的节点保持原样的大小关系

而IDDFA中的A*下界函数就不需要这个性质了,只要是下界即可。

显然这个具体问题的天然的估计函数就是从此点到目标点的最短路。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int M =1e5+100;
const int N =1e3+10;
const int inf = 0x3f3f3f3f ;
struct Edge
{
    int v;
    int w;
    int next;
}es1[M],es2[M];
int head1[N],head2[N];
int n,m;
int s,g,k;
bool vis[N];
int dis[N];
void spfa()
{
    memset(vis,0,sizeof(vis));
    dis[g]=0;
    queue<int >q;
    q.push(g);
    vis[g]=true;
    while(!q.empty())
    {
        int cur=q.front();
        q.pop();
        vis[cur]=false;
        for(int i=head2[cur];~i;i=es2[i].next)
        {
            int v=es2[i].v,w=es2[i].w;
            if(dis[v]>dis[cur]+w)
            {
                dis[v]=dis[cur]+w;
                if(vis[v]) continue;
                vis[v]=true;
                q.push(v);
            }
        }
    }
}
struct node
{
    int u;
    int g,f;
    bool operator < (const node &a) const
    {
        return a.f<f; //按f最小堆
    }
};
int A_star()
{
    int cnt=0;
    priority_queue<node> que;
    if(dis[s]==inf) return -1;  //剪枝
    node st;
    st.g=0,st.f=dis[s],st.u=s;
    que.push(st);
    while(!que.empty())
    {
        node cur=que.top();
        que.pop();
        if(cur.u==g) cnt++;
        if(cnt==k) return cur.g;
        for(int i=head1[cur.u];~i;i=es1[i].next)
        {
            int v=es1[i].v,w=es1[i].w;
            node nxt;
            nxt.u=v,nxt.g=cur.g+w,nxt.f=nxt.g+dis[v];
            que.push(nxt);
        }
    }
    return -1;
}
void ini()
{
    fill(dis,dis+1005,inf);
    memset(head1,-1,sizeof(head1));
    memset(head2,-1,sizeof(head2));
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        ini();
        for(int i=1;i<=m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            es1[i].v = v,es1[i].w=w,es1[i].next=head1[u];
            head1[u]=i;
            es2[i].v=u,es2[i].w=w,es2[i].next=head2[v];
            head2[v]=i;
        }
        scanf("%d%d%d",&s,&g,&k);
        if(s==g) k++;   //易错,当s和g重合时,没经过其他路不算一种方法
        spfa();
        printf("%d\n",A_star());
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值