1975: [Sdoi2010]魔法猪学院

题目链接

题目大意:找出1~k短路

题解:x的估价函数 f(x) 取x到结束节点的最短路,这个是准确值,因此复杂度有保证
按广搜的方式扩展节点,每次优先扩展估价+实际最小的节点
第i次扩展到目标节点,代表找到了第i短路

我的收获:org

#include<cstdio>  
#include<cstring>  
#include<cstdlib>  
#include<cmath>  
#include<algorithm>  
#include<iostream>  
#include<queue>  
#define maxn 5010  
#define maxm 201000  
#define inf 1e12  

using namespace std;  

struct yts  
{  
    int now;  
    double g;  
};  

double dis[maxn];  
int q[maxn];  
bool vis[maxn];  

bool operator<(yts x,yts y)  
{  
    return x.g+dis[x.now]>y.g+dis[y.now];  
}  

priority_queue<yts> Q;  

int head[maxn],to[maxm],next[maxm];  
double len[maxm],Len[maxm];  
int Head[maxn],To[maxm],Next[maxm];  
int n,m,num,ans,x,y,S,T,Num;  
double e,z;  

void addedge(int x,int y,double z)  
{  
    num++;to[num]=y;len[num]=z;next[num]=head[x];head[x]=num;  
}  

void add(int x,int y,double z)  
{  
    Num++;To[Num]=y;Len[Num]=z;Next[Num]=Head[x];Head[x]=Num;  
}  

void spfa()  
{  
    for (int i=S;i<=T;i++) dis[i]=inf;  
    dis[T]=0;vis[T]=1;q[1]=T;  
    int l=0,r=1;  
    while (l!=r)  
    {  
        l++;if (l==maxn) l=0;  
        int x=q[l];  
        for (int p=Head[x];p;p=Next[p])  
          if (dis[x]+Len[p]<dis[To[p]])  
          {  
            dis[To[p]]=dis[x]+Len[p];  
            if (!vis[To[p]])  
            {  
                r++;if (r==maxn) r=0;  
                vis[To[p]]=1;q[r]=To[p];  
            }  
          }  
        vis[x]=0;  
    }  
}  

void Astar()  
{  
    Q.push((yts){S,0});  
    while (!Q.empty())  
    {  
        yts x=Q.top();Q.pop();  
        if (x.now==T)  
        {  
            e-=x.g;  
            if (e<0) return;  
            ans++;  
            continue;  
        }  
        if (x.g+dis[x.now]>e) continue;  
        for (int p=head[x.now];p;p=next[p]) Q.push((yts){to[p],x.g+len[p]});  
    }  
}  

int main()  
{  
    scanf("%d%d%lf",&n,&m,&e);  
    for (int i=1;i<=m;i++)  
    {  
        scanf("%d%d%lf",&x,&y,&z);  
        addedge(x,y,z);add(y,x,z);  
    }  
    S=1,T=n;  
    spfa();  
    Astar();  
    printf("%d\n",ans);  
    return 0;  
}  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值