poj2449 Remmarguts' Date(A*模板)

题记

这题真的改死我(再见
哦还被diss了好久(再见
嗯感觉还有坑!(再见


题意

poj2449
有n条边,求s到t的第k短路


题解

这这这就A*算法模板吧【捂脸】
A*是啥呢
有人说是启发式合并吧…
我们定义一个评估值f(x)=g(x)+h(x)(例如求k短路中g(x)表示已经走了多远,h(x)表示从这个点到终点的最短路)f(x)越小就意味着越好咯,我们每次都去寻找最小的f(x)来进行操作,那不就很妙了

那k短路怎么求呢
我们就先求出每个点到终点的最短路——把图反过来..从t做最短路【捂脸】 这样就求出来了h(x)
然后就..每次做一个点,然后…求一个f(x),扔进优先队列里..
最后t出现k次也就可以了

嗯这里..我被鄙视了…我..开始认为..可以随便选一个点,如果这个点出现k次就直接返回它的g(x)+h(x)..然而有可能出现后面比它短..

哦对这题..假如s==t,这题认为..不能直接到…所以它的第一短路也要走一圈【捂脸】


代码

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define N 1100 
#define M 100010
#define inf 1000000000
int num1=0,num2=0,n,m,s,t,k,h1[N],h2[N],d[N],flag[N]; 
struct node1{int x,y,z,next;}mp1[M],mp2[M];
struct node{
    int v,c;
    node(int vv,int cc) : v(vv),c(cc){}
    friend bool operator < (node x,node y){return x.c+d[x.v]>y.c+d[y.v];}
};
void insert1(int x,int y,int z){mp1[++num1].x=x;mp1[num1].y=y;mp1[num1].z=z;mp1[num1].next=h1[x];h1[x]=num1;}
void insert2(int x,int y,int z){mp2[++num2].x=x;mp2[num2].y=y;mp2[num2].z=z;mp2[num2].next=h2[x];h2[x]=num2;}
void spfa(){
    queue<int>Q;Q.push(t);
    for(int i=1;i<=n;i++) d[i]=inf;d[t]=0;
    memset(flag,0,sizeof(flag));flag[t]=1;
    while(!Q.empty()){
        int u=Q.front();Q.pop();flag[u]=0;
        for(int i=h1[u];i;i=mp1[i].next){
            int v=mp1[i].y;
            if(d[v]>d[u]+mp1[i].z){
                d[v]=d[u]+mp1[i].z;
                if(!flag[v]){
                    flag[v]=1;
                    Q.push(v);
                }
            }
        }
    }
}
int astar(){
    if(d[s]==inf) return -1;
    priority_queue<node>p;
    int cnt=0;p.push(node(s,0));
    while(!p.empty()){
        node u=p.top();p.pop();
        if(u.v==t){
            cnt++;
            if(cnt==k) return u.c;
        }
        for(int i=h2[u.v];i;i=mp2[i].next){
            int y=mp2[i].y;
            p.push(node(y,u.c+mp2[i].z));
        }
    }return -1;
}
int main(){
    while(scanf("%d%d",&n,&m)>0){
        memset(h1,0,sizeof(h1));num1=0;
        memset(h2,0,sizeof(h2));num2=0;
        for(int i=1;i<=m;i++){
            int x,y,z;scanf("%d%d%d",&x,&y,&z);
            insert1(y,x,z);insert2(x,y,z); 
        }scanf("%d%d%d",&s,&t,&k);
        spfa();
        printf("%d\n",astar());
    }
    return 0;
} 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值