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;
}

 

posted @ 2018-11-08 12:47  Gloid  阅读(188)  评论(0编辑  收藏  举报