[BZOJ1975][Sdoi2010]魔法猪学院

原题地址

k短路.

A*求k短路就是用估价函数优化暴力搜索,选择估价最短的状态优先扩展,然后发现一个性质:第k短的路径第k个被搜到(出队),这个MS挺显然…

然后k短路就讲完了…

这题原题空限是256M,BZOJ上64M,于是怒被卡,被出题人坑了一波…

AC code:

#include <cstdio>
#include <queue>
using namespace std;
typedef long double llf;
const int N=200010;
const int INF=1<<29;
int n,m,S,T,tot,K,ans;
int h1[N],h2[N],cnt[N];
llf dist[N];
llf e;

struct edge{
    int u,v,next;
    llf w;

    edge() {}
    edge(int u,int v,llf w,int next):u(u),v(v),w(w),next(next) {}
}E1[N],E2[N];

struct data{
    int u;
    llf g;

    data() {}
    data(int u,llf g):u(u),g(g) {}

    friend bool operator<(data x,data y){
        return x.g+dist[x.u]>y.g+dist[y.u];
    }
};

void addedge(int u,int v,llf w){
    E1[++tot]=edge(u,v,w,h1[u]);
    h1[u]=tot;
    E2[tot]=edge(v,u,w,h2[v]);
    h2[v]=tot;
}

void SPFA(){
    queue<int> Q;
    for(int i=1;i<=n;i++) dist[i]=INF;
    dist[T]=0;
    Q.push(T);
    while(!Q.empty()){
        int x=Q.front();
        Q.pop();
        for(int i=h2[x];i;i=E2[i].next){
            if(dist[x]+E2[i].w>=dist[E2[i].v]) continue;
            dist[E2[i].v]=dist[x]+E2[i].w;
            Q.push(E2[i].v);
        }
    }
}

void work(){
    priority_queue<data> Q;
    Q.push(data(S,0));
    while(!Q.empty()){
        data x=Q.top();
        Q.pop();
        cnt[x.u]++;
        K=cnt[T]+(int)(e/(x.g+dist[x.u]));
        if(x.u==T){
            if(x.g>e) break;
            else{
                ans++;
                e-=x.g;
                continue;
            }
        }
        for(int i=h1[x.u];i;i=E1[i].next) 
            if(x.g+dist[x.u]<=e&&cnt[E1[i].v]<=K) Q.push(data(E1[i].v,x.g+E1[i].w));
    }
    printf("%d\n",ans);
}

int main(){
    freopen("BZOJ1975.in","r",stdin);
    freopen("BZOJ1975.out","w",stdout);

    scanf("%d%d%lf",&n,&m,&e);
    S=1;T=n;
    for(int i=1;i<=m;i++){
        int u,v;
        llf w;
        scanf("%d%d%lf",&u,&v,&w);
        addedge(u,v,w);
    }
    SPFA();
    work();

    fclose(stdin);
    fclose(stdout);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值