POJ 2449 A*经典水题

来源:互联网 发布:知乎阿里云免费开通码 编辑:程序博客网 时间:2024/06/06 17:26

先求每个点到目地T的最短距离。

这一步可以将图的每条边反向,做单源最短路求得。

然后就是在图上搜索。

可以用优先队列来实现搜索状态的筛选。

f=g+h

g为搜索到此点已经走过的距离,h为此点到T的最短距离。

当第K次搜到T,此时的g+h就是第K短路。


#include<cstdio>#include<cstring>#include<algorithm>#include<cstdlib>#include<iostream>#include<queue>using namespace std;const int INF=0x3f3f3f3f;int N,M;int S,T,K;struct edge{    int to,cost,next;}E1[100005],E2[100005];int esize1,esize2;int head1[1005],head2[1005];int d[1005];void init(){    memset(head1,-1,sizeof(head1));    memset(head2,-1,sizeof(head2));    esize1=esize2=0;}void addedge(int from,int to,int cost){    E1[esize1].to=to;    E1[esize1].cost=cost;    E1[esize1].next=head1[from];    head1[from]=esize1++;    E2[esize2].to=from;    E2[esize2].cost=cost;    E2[esize2].next=head2[to];    head2[to]=esize2++;}void dij(){    typedef pair<int,int> P;    memset(d,0x3f,sizeof(d));    priority_queue<P,vector<P>,greater<P> > que;    d[T]=0;    que.push(P(0,T));    while(!que.empty())    {        P tmp=que.top(); que.pop();        if(d[tmp.second]<tmp.first) continue;        for(int i=head2[tmp.second];i!=-1;i=E2[i].next)        {            if(d[E2[i].to]>tmp.first+E2[i].cost)            {                d[E2[i].to]=tmp.first+E2[i].cost;                que.push(P(d[E2[i].to],E2[i].to));            }        }    }}struct step{    int v;    int f,h;    step (int a=0,int b=0,int c=0):v(a),f(b),h(c){}    bool operator>(const step &tmp)const    {        return f+h>tmp.f+tmp.h;    }};int astar(){    priority_queue<step,vector<step>,greater<step> > que;    que.push(step(S,0,d[S]));    int cnt=0;    while(!que.empty())    {        step now=que.top(); que.pop();        //printf("v=%d f=%d h=%d\n",now.v,now.f,now.h);        //system("pause");        if(now.v==T)        {            cnt++;            if(cnt==K) return now.f+now.h;        }        for(int i=head1[now.v];i!=-1;i=E1[i].next)        {            que.push(step(E1[i].to, now.f+E1[i].cost ,d[E1[i].to]));        }    }    return -1;}int main(){    while(~scanf("%d%d",&N,&M))    {        init();        int a,b,c;        for(int i=0;i<M;i++)        {            scanf("%d%d%d",&a,&b,&c);            addedge(a,b,c);        }        scanf("%d%d%d",&S,&T,&K);        if(S==T) K++;        dij();        printf("%d\n",astar());    }}


0 0
原创粉丝点击