BZOJ1975 SDOI2010魔法猪学院(启发式搜索+最短路+堆)
对反图跑最短路求出每个点到终点的最短路径,令其为估价函数大力A*,第k次到达某个点即是找到了到达该点的非严格第k短路,因为估价函数总是不大于实际值。bzoj可能需要手写堆。正解是可持久化可并堆,至今是第二次见到这个那当然是不学啦。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define N 5010 #define M 200010 char getc(){char c=getchar();while (c==10||c==13||c==32) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,p[N],cnt[N],t,ans; bool flag[N]; double tot,d[N]; struct data{int to,nxt;double len; }edge[M]; struct data2 { int x;double d,r; bool operator <(const data2&a) const { return d+r<a.d+a.r||d+r==a.d+a.r&&d>a.d; } }; struct heap { data2 a[M*12];int n; bool empty(){return n==0;} data2 top(){return a[1];} void push(data2 x) { a[++n]=x;int k=n; while (k>1&&a[k]<a[k>>1]) swap(a[k],a[k>>1]),k>>=1; } void pop() { a[1]=a[n--];int k=1; while ((k<<1)<=n) { int x=k<<1; if (x<n&&a[x|1]<a[x]) x|=1; if (a[x]<a[k]) swap(a[x],a[k]),k=x;else break; } } }q; void addedge(int x,int y,double z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;} namespace reversegraph { int p[N]={0},t=0; struct data{int to,nxt;double len;}edge[M]; void addedge(int x,int y,double z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;} void dijkstra() { for (int i=1;i<n;i++) d[i]=1e8; q.push((data2){n,0,0}); for (;;) { while (!q.empty()&&flag[q.top().x]) q.pop(); if (q.empty()) break; data2 x=q.top();q.pop();flag[x.x]=1; for (int i=p[x.x];i;i=edge[i].nxt) if (x.d+edge[i].len<d[edge[i].to]) { d[edge[i].to]=x.d+edge[i].len; q.push((data2){edge[i].to,d[edge[i].to],0}); } } } } void Astar(int lim) { q.push((data2){1,0,d[1]}); while (!q.empty()) { data2 x=q.top();q.pop(); cnt[x.x]++; if (x.d+x.r>tot) break; if (x.x==n) {tot-=x.d,ans++;continue;} for (int i=p[x.x];i;i=edge[i].nxt) if (cnt[edge[i].to]<lim) q.push((data2){edge[i].to,x.d+edge[i].len,d[edge[i].to]}); } } int main() { #ifndef ONLINE_JUDGE freopen("bzoj1975.in","r",stdin); freopen("bzoj1975.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),m=read();cin>>tot; for (int i=1;i<=m;i++) { int x=read(),y=read();double z;scanf("%lf",&z); addedge(x,y,z);reversegraph::addedge(y,x,z); } reversegraph::dijkstra(); Astar(tot/d[1]); cout<<ans; return 0; }