k短路-洛谷P2483 [SDOI2010]魔法猪学院

https://daniu.luogu.org/problem/show?pid=2483

A*求k短路和dijkstra算法很相似。
我们先把边反向,预处理出h(x),表示从x到T的最短路径长度。
另g(x)为目前为止从起点到x的距离。
以(h(x)+g(x))为关键字维护一个小根堆,然后跑dijkstra即可。
第k次到达终点的时候输出。
正确性显然。

这个是我们xxy学长给我们讲的,其实已经很明了了;
当然Fop_zz的博客有详细的介绍;
这里
我就不多说了;
然后SPFA炸了;
改好就AC了;
这;
当然内存是在bz过不了的;

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<queue>
#define Ll long long
using namespace std;
double h[5010];
struct T{
    int x;
    double v;
    bool operator < (const T &a) const
    {
        return a.v+h[a.x]<v+h[x];
    }
};
priority_queue<T>Q;
struct cs{
    int to,next;
    double v;
}a[200010];
struct In{
    int x,y;
    double z;
}r[200010];
int head[5010],ll;
int q[400010];
bool vi[5010]; 
int n,m,ans;
double money;
void init(int x,int y,double z){
    a[++ll].to=y;
    a[ll].v=z;
    a[ll].next=head[x];
    head[x]=ll;
}
void SPFA(int S){
    int l=0,r=1;
    q[1]=S;
    for(int i=0;i<=n;i++)h[i]=1e9;
    h[S]=0;
    while(r>l){
        int x=q[++l];
        for(int k=head[x];k;k=a[k].next)
            if(a[k].v+h[x]<h[a[k].to]){
                h[a[k].to]=a[k].v+h[x];
                if(!vi[a[k].to]){
                    vi[a[k].to]=1;
                    q[++r]=a[k].to;
                }
            }
        vi[x]=0;
    }
}
void Dijkstra(int S,int E){
    T c;
    c.v=0;
    c.x=S;
    Q.push(c);
    while(!Q.empty()){
        c=Q.top();
        Q.pop();
        if(c.x==E){
            money-=c.v;
            if(money<0)return;
            ans++;
        }
        for(int k=head[c.x];k;k=a[k].next){
            T p;
            p.x=a[k].to;
            p.v=c.v+a[k].v;
            Q.push(p);          
        }
    }
}
int main(){
    scanf("%d%d%lf",&n,&m,&money);
    for(int i=1;i<=m;i++){
        scanf("%d%d%lf",&r[i].x,&r[i].y,&r[i].z);
        init(r[i].y,r[i].x,r[i].z);
    }
    SPFA(n);
    memset(head,0,sizeof head);
    ll=0;
    for(int i=1;i<=m;i++)init(r[i].x,r[i].y,r[i].z);
    Dijkstra(1,n);
    printf("%d",ans);
}

转载于:https://www.cnblogs.com/largecube233/p/6797872.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值