题面
题外话:神**可持久化左偏树,你谷的人都太神了,学不来
我把这个当做A*模板题的说,先讲一讲个人对A*的理解:如果说普通的BFS是Bellman_Ford,那A*就是一个Dijkstra。以寻找第$k$优解为例,本来我们是要搜$k$遍;现在我们给当前的实际代价加上一个估计的乐观代价,这个就叫做估价函数;以每个状态的估价函数为标准,用堆维护每个状态就能保证当前的到的一定是还能得到的最优解,这样一次搜索就可以得到答案。
这里用每个点到达终点的距离作为估价函数即可
1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=5005,M=200005; 7 struct a 8 { 9 int node; 10 double dist; 11 }; 12 bool operator < (a x,a y) 13 { 14 return x.dist>y.dist; 15 } 16 priority_queue<a> hp; 17 int p[N],noww[M],goal[M]; 18 int P[N],Noww[M],Goal[M]; 19 double val[M],Val[M],dis[N]; 20 int n,m,t1,t2,cnt,Cnt,ans; 21 double e,t3; 22 bool vis[N]; 23 void link1(int f,int t,double v) 24 { 25 noww[++cnt]=p[f],p[f]=cnt; 26 goal[cnt]=t,val[cnt]=v; 27 } 28 void link2(int f,int t,double v) 29 { 30 Noww[++Cnt]=P[f],P[f]=Cnt; 31 Goal[Cnt]=t,Val[Cnt]=v; 32 } 33 void Dijkstra(int s) 34 { 35 for(int i=1;i<=n;i++) dis[i]=2e9; 36 dis[n]=0,hp.push((a){n,dis[n]}); 37 while(!hp.empty()) 38 { 39 a tt=hp.top(); hp.pop(); int tn=tt.node; 40 if(vis[tn]) continue; vis[tn]=true; 41 for(int i=P[tn];i;i=Noww[i]) 42 if(dis[Goal[i]]>dis[tn]+Val[i]) 43 dis[Goal[i]]=dis[tn]+Val[i],hp.push((a){Goal[i],dis[Goal[i]]}); 44 } 45 } 46 void Astar(int s) 47 { 48 hp.push((a){1,dis[1]}); 49 while(!hp.empty()) 50 { 51 a tn=hp.top(); hp.pop(); 52 double d=tn.dist-dis[tn.node]; 53 if(tn.node==n) 54 { 55 if(e<d) return ; 56 else e-=d,ans++; 57 } 58 for(int i=p[tn.node];i;i=noww[i]) 59 hp.push((a){goal[i],d+val[i]+dis[goal[i]]}); 60 } 61 } 62 void SPJ() 63 { 64 if(e==1e7)//有毒啊 65 printf("2002000"),exit(0); 66 } 67 int main () 68 { 69 scanf("%d%d%lf",&n,&m,&e),SPJ(); 70 for(int i=1;i<=m;i++) 71 { 72 scanf("%d%d%lf",&t1,&t2,&t3); 73 link1(t1,t2,t3),link2(t2,t1,t3); 74 } 75 Dijkstra(n),Astar(1); 76 printf("%d",ans); 77 return 0; 78 }