【模板】BZOJ1975: [Sdoi2010]魔法豬學院-A*演算法-k短路
阿新 • • 發佈:2019-01-07
題解
啟發式搜尋中的估價函式/A*演算法
先跑一遍節點n的最短路
此題中用小根堆維護
這裡的就是當前點到目標節點n的最短路距離。是起點到當前點的目前狀態所走過的路徑長度。
程式碼
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<queue>
#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;i<n;++i) dis[i]=inf;
Q.push(n);vis[n]=1;
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]<f[y] && y<cnt) y|=1;
while(y<=cnt && f[y]<f[x]){
swap(f[y],f[x]);swap(in[y],in[x]);
x=y;y=x<<1;if(f[y|1]<f[y] && y<cnt) y|=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);
}