zoukankan      html  css  js  c++  java
  • BZOJ-1975: 魔法猪学院 (K短路:A*+SPFA)

    题意:有N种化学元素,有M种转化关系,(u,v,L)表示化学物质由u变为v需要L能量,现在你有E能量,问最多有多少种不同的途径,使得1转为为N,且总能量不超过E。

    思路:可以转为为带权有向图,即是求前K(K未知)短路,满足前K短路的边权和小于等于E,求K。

    BZOJ上面提交的时间和空间都还不错。但是洛谷卡空间,我一顿操作还是没卡过去。

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define uint unsigned short int
    #define rep(i,a,b) for(register int i=a;i<=b;i++)
    using namespace std;
    const int maxn=5010;
    const int maxm=200010;
    const double inf=0x7fffffff;
    int Laxt1[maxn],Next1[maxm],cnt1; uint To1[maxm],To2[maxm];
    int Laxt2[maxn],Next2[maxm],cnt2;
    double dis[maxn],Len1[maxm],Len2[maxm];
    int N,M,vis[maxn],ans; double E;
    void read(int &x){
        x=0; char c=getchar();
        while(c>'9'||c<'0') c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    }
    struct in{
        uint x; float f;
        in(){}
        in(uint xx,float ff):x(xx),f(ff){};
        friend bool operator <(in w,in v){
            return w.f+dis[w.x]>v.f+dis[v.x];
        }
    };
    void add(int u,int v,double L)
    {
        Next1[++cnt1]=Laxt1[u]; Laxt1[u]=cnt1; To1[cnt1]=v; Len1[cnt1]=L;
        Next2[++cnt2]=Laxt2[v]; Laxt2[v]=cnt2; To2[cnt2]=u; Len2[cnt2]=L;
    }
    uint q1[5010]; int head=0,tail=0;
    void dijkstra()
    {
        rep(i,1,N-1) dis[i]=inf;
        q1[++head]=N;
        while(head!=tail){
            tail++; if(tail==N+1) tail=1;
            uint u=q1[tail];   vis[u]=0;
            for(int i=Laxt2[u];i;i=Next2[i]){
                uint v=To2[i];
                if(dis[v]>dis[u]+Len2[i]){
                    dis[v]=dis[u]+Len2[i];
                    if(!vis[v]){
                        vis[v]=1;
                        head++; if(head==N+1) head=1;
                        q1[head]=v;
                    }
                }
            }
        }
    }
    void Astar(int K)
    {
        priority_queue<in>q;
        rep(i,1,N) vis[i]=0;
        q.push(in(1,0));
        while(!q.empty()){
            in T=q.top();q.pop();
            if(T.f>E) return ;
            int u=T.x; vis[u]++;
            if(u==N){
                E-=T.f;
                if(E<0) return ;
                ans++;
                continue;
            }
            if(vis[u]>=K) continue;
            for(int i=Laxt1[u];i;i=Next1[i]){
                int v=To1[i];
                q.push(in(v,T.f+Len1[i]));
            }
        }
    }
    int main()
    {
        scanf("%d%d%lf",&N,&M,&E);
        int u,v; double L;
        rep(i,1,M) {
            read(u); read(v);
            scanf("%lf",&L);
            add(u,v,L);
        }
        dijkstra();
        Astar(E/dis[1]+1);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    vs利用正则表达式统计代码行数
    C/C++/MFC的include搜索顺序
    afxwin.h afx.h afxver.h afxv_w32.h windows.h包含顺序
    C/C++中内存块置0的三种方法:memset,ZeroMemory,SecurZeroMemory
    关于socket阻塞与非阻塞情况下的recv、send、read、write返回值
    vs2008工程设置里添加宏
    使用共享网卡的NAT模式配置VMware中的CentOS的上网功能
    VMware10 安装centos6.7 设置NAT模式
    《大道至简》第7,8章读书笔记
    ie11浏览器和chrome浏览器对于bgsound和background的一些区别
  • 原文地址:https://www.cnblogs.com/hua-dong/p/11156299.html
Copyright © 2011-2022 走看看