【模板】BZOJ1975: [Sdoi2010]魔法猪学院-A*算法-k短路

传送门:bzoj1975

题解

启发式搜索中的估价函数/A*算法
先跑一遍节点n的最短路
此题中用小根堆维护 (fi,i) ( f i , i )
fi=gi+hi f i = g i + h i
这里的 hi h i 就是当前点到目标节点n的最短路距离。 gi g i 是起点到当前点的目前状态所走过的路径长度。


代码

 #include
#include
#include
#include
#define db double
using namespace std;
const int N=5e3+10,M=2e5+10,H=5e6+10;
const db inf=100000000.0,eps=1e-6;
int n,m,ans;
int head[2][N],to[2][M],nxt[2][M],tot;
int vis[N],in[H],cnt;db w[M],E,f[H],dis[N];
queue<int>Q;

inline int rd()
{
    char ch=getchar();int x=0,f=1;
    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
    return x*f;
}

inline void lk(int u,int v,db c){
    to[0][++tot]=v;nxt[0][tot]=head[0][u];head[0][u]=tot;
    to[1][tot]=u;nxt[1][tot]=head[1][v];head[1][v]=tot;
    w[tot]=c;
}

inline void spfa()
{
    int x,i,j;
    dis[n]=0.0;
    for(i=1;i1;
    while(!Q.empty()){
        x=Q.front();Q.pop();vis[x]=0;
        for(i=head[1][x];i;i=nxt[1][i]){
            j=to[1][i];
            if(dis[j]>dis[x]+w[i]){
                dis[j]=dis[x]+w[i];
                if(!vis[j]){vis[j]=1;Q.push(j);}
            }
        }
    }
}

inline void pu(db val,int tag)
{
    int x=++cnt,fa=x>>1;
    in[cnt]=tag;f[cnt]=val;
    while(fa && f[fa]>val){
        swap(f[fa],f[x]);swap(in[fa],in[x]);
        x=fa;fa=fa>>1;
    }
}

inline void po()
{
    swap(f[1],f[cnt]);swap(in[1],in[cnt]);cnt--;
    int x=1,y=x<<1;if(f[y|1]1;
    while(y<=cnt && f[y]1;if(f[y|1]1;
    }
}

inline void astar()
{
    int i,j,x;db d;
    pu(dis[1],1);
    while(cnt){
        x=in[1];d=f[1];
        po();
        if(x==n){E-=d;if(E>=eps) ans++;else return;}
        for(i=head[0][x];i;i=nxt[0][i]){
            j=to[0][i];
            pu(d-dis[x]+w[i]+dis[j],j);
        }
    }
}

int main(){
    int i,j,ix,iy;db iz;
    n=rd(),m=rd();scanf("%lf",&E);
    for(i=1;i<=m;++i){ix=rd();iy=rd();scanf("%lf",&iz);lk(ix,iy,iz);}
    spfa();
    astar();
    printf("%d\n",ans);
}

你可能感兴趣的:(A*算法)