• 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
    ";
    #else
        const char LL[]="%lld
    ";
    #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;
    }
  • 相关阅读:
    js开发笔记
    安全相关开发笔记
    常用.NET库使用总结
    Windows使用总结
    .NET Web开发笔记
    Unity插件使用总结
    WinForm开发笔记
    C#开发笔记
    iTunes使用总结
    Mac使用总结
  • 原文地址:https://www.cnblogs.com/Gloid/p/9928404.html
Copyright © 2020-2023  润新知