A*模板

来源:互联网 发布:淘宝买游戏账号被找回 编辑:程序博客网 时间:2024/06/06 03:32

求第k短路。

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<queue>using namespace std;const int INF = 1e9+7;int n,m,ts,te,k,tot1,tot2,ru,rv,rw;int first1[100010],nxt1[100010],first2[100010],nxt2[100010],dis[100010];bool used[100010];struct edge{    int u,v,w;}l1[100010],l2[100010];struct st{    int num,d;    bool operator < (st a)const    {        return d>a.d;    }}p1[100010];priority_queue<st>q2;struct heap{    int g,h,num;    bool operator < (heap a)const    {        return (g+h)>(a.g+a.h);    }}p2[100010];priority_queue<heap>q1;void build_1(int f,int t,int c){    l1[++tot1]=(edge){f,t,c};    nxt1[tot1]=first1[f];    first1[f]=tot1;}void build_2(int f,int t,int c){    l2[++tot2]=(edge){f,t,c};    nxt2[tot2]=first2[f];    first2[f]=tot2;}void geth(){    for(int i=1;i<=n;i++)    dis[i]=INF;    dis[te]=0;    q2.push((st){te,0});    while(!q2.empty())    {        st h=q2.top();        q2.pop();        if(used[h.num]==1)        continue;        used[h.num]=1;        for(int i=first2[h.num];i!=-1;i=nxt2[i])        {            int x=l2[i].v;            if(dis[x]>dis[h.num]+l2[i].w)            {                dis[x]=dis[h.num]+l2[i].w;                q2.push((st){x,dis[x]});            }        }    }}void Astar(){    geth();    q1.push((heap){0,dis[ts],ts});    while(!q1.empty())    {        heap h=q1.top();        q1.pop();        if(h.num==te)        {            tot1++;            if(tot1>=k)            {                printf("%d",h.g);                return;            }        }        for(int i=first1[h.num];i!=-1;i=nxt1[i])        {            int x=l1[i].v;            q1.push((heap){h.g+l1[i].w,dis[x],x});        }    }    printf("-1");}int main(){    memset(first2,-1,sizeof(first2));    memset(first1,-1,sizeof(first1));    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++)    {        scanf("%d%d%d",&ru,&rv,&rw);        build_1(ru,rv,rw);        build_2(rv,ru,rw);    }    scanf("%d%d%d",&ts,&te,&k);    if(ts==te)    k++;    tot1=0;    Astar();    return 0;}


注意估价函数设置,对于求第k短路而言,估价函数的影响使得Dijkstra过程中只会依次严格经过第1,2…k短路上的边到达终点。

求第k短路也可以使用Dijkstra,第k次找到终点的路径即为由起点到终点的第k短路。

代码

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<queue>using namespace std;typedef long long ll;int n,m,ts,te,k,ru,rv,rw,tot;int first[100010],nxt[100010],cnt[100010];bool flag;ll ans;struct edge{    int u,v,w;}l[100010];struct st{    int num;    ll d;}p;bool operator < (st a,st b){    return  a.d>b.d;}priority_queue<st>q;void build(int f,int t,int c){    l[++tot]=(edge){f,t,c};    nxt[tot]=first[f];    first[f]=tot;}void Dijkstra(){    q.push((st){ts,0});    while(!q.empty())    {        st h=q.top();        q.pop();        if(cnt[h.num]>=k)//十分重要的剪枝        continue;        cnt[h.num]++;        if(h.num==te&&cnt[h.num]==k)        {            flag=1;            ans=h.d;            break;        }        for(int i=first[h.num];i!=-1;i=nxt[i])        {            int x=l[i].v;            q.push((st){x,h.d+l[i].w});        }    }}int main(){    memset(first,-1,sizeof(first));    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++)    {        scanf("%d%d%d",&ru,&rv,&rw);        build(ru,rv,rw);    }    scanf("%d%d%d",&ts,&te,&k);    tot=0;    Dijkstra();    if(flag)    printf("%I64d",ans);    else printf("-1");    return 0;}
原创粉丝点击