1. 程式人生 > >BZOJ1975 SDOI2010魔法豬學院(啟發式搜索+最短路)

BZOJ1975 SDOI2010魔法豬學院(啟發式搜索+最短路)

zoj size per pty stdout int can bre return

  對反圖跑最短路求出每個點到終點的最短路徑,令其為估價函數大力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; }

BZOJ1975 SDOI2010魔法豬學院(啟發式搜索+最短路)