Live2d Test Env

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\n",ans);
    return 0;
}

 

posted @ 2019-07-09 11:39  nimphy  阅读(183)  评论(0编辑  收藏  举报