你谷數據夠強了,之前的A*應該差很少死掉了。html
因此,小夥伴們快來一塊兒把YL頂上去把!戳這裏!ios
俞鼎力的課件c++
須要掌握的內容:spa
Dijkstra構建最短路徑樹。code
可持久化堆(使用左偏樹,因其有二叉樹結構且能動態合併。構建方法相似可持久化線段樹)。htm
#include<bits/stdc++.h> #define RG register #define R RG int using namespace std; const int N=5009,M=4e5+9; int p,he[N],re[N],ne[M],to[M],f[N],rt[N]; double w[M],d[N];bool vis[N]; struct Heap{ double w; int lc,rc,dep,end; }t[M];//不要問我爲何過了 struct Node{ double w;int x; inline bool operator<(RG Node a)const{ return w>a.w; } }; priority_queue<Node>q; int merge(R x,R y,R op){//左偏樹合併,op控制是否複製版本 if(!(x&&y))return x+y; if(t[x].w>t[y].w)swap(x,y); if(op)t[++p]=t[x],x=p; t[x].rc=merge(t[x].rc,y,op); if(t[t[x].lc].dep<t[t[x].rc].dep)swap(t[x].lc,t[x].rc); t[x].dep=t[t[x].rc].dep+1; return x; } int main(){ ios::sync_with_stdio(0); R n,m,i,x,y,ans=0; RG double E,now; cin>>n>>m>>E; for(i=1;i<=m;++i){ cin>>x>>y>>w[i]; ne[ i ]=he[x];to[he[x]= i ]=y; ne[i+m]=re[y];to[re[y]=i+m]=x; } for(x=1;x<n;++x)d[x]=1e18; q.push((Node){0,n});//Dijkstra開始 while(!q.empty()){ x=q.top().x;q.pop(); if(vis[x])continue; vis[x]=1; for(i=re[x];i;i=ne[i]) if(d[y=to[i]]>d[x]+w[i-m]) q.push((Node){d[y]=d[x]+w[i-m],y}); } for(x=1;x<=n;++x){ if(d[x]==1e18)continue; for(i=he[x];i;i=ne[i]){ if(d[x]==d[y=to[i]]+w[i]&&!f[x])f[x]=y;//構建最短路樹 else if(d[y]!=1e18){ t[++p]=(Heap){d[y]+w[i]-d[x],0,0,1,y}; rt[x]=merge(rt[x],p,0); } } q.push((Node){d[x],x}); } while(!q.empty()){ x=q.top().x;q.pop(); if(f[x])rt[x]=merge(rt[x],rt[f[x]],1);//可持久化 } if(E>=d[1])E-=d[1],++ans; if(rt[1])q.push((Node){t[rt[1]].w,rt[1]}); while(!q.empty()){ now=q.top().w;x=q.top().x;q.pop(); if(E<now+d[1])break; E-=now+d[1];++ans; if((y=t[x].lc))q.push((Node){now-t[x].w+t[y].w,y}); if((y=t[x].rc))q.push((Node){now-t[x].w+t[y].w,y}); if((y=rt[t[x].end]))q.push((Node){now+t[y].w,y}); } printf("%d\n",ans); return 0; }