BZOJ 1975 SDOI2010 魔法猪学院 A*k短路

题目大意:给定一个值E 求起点到终点的最多条路径 使长度之和不超过E

k短路的A*算法……每一个点有一个估价函数=g[x]+h[x] 当中g[x]是从源点出发已经走了的长度 h[x]是从这个点到汇点的最短路

首先先在反图上跑一遍SPFA求出每一个点的h[x],然后将源点的g[x]+h[x]增加堆 每次取出堆顶时将堆顶的g[x]向所连接的边扩展 第k次取出汇点即是答案

当中有一个剪枝就是当第k+1次取出某个点时不继续拓展 防止MLE 可是这里k未知 我们能够对k进行估价处理 初始k=floor(E/最短路长度) 然后每次取出汇点时更新k k=cnt[n]+floor(E/当前路径长度)

比較丧病的是这题卡priority_queue……这东西的内存是手写堆的二倍 因为卡内存 所以会挂 能够手写堆 我写了可并堆+垃圾回收……

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 5050
using namespace std;
struct abcd{
    int pos;
    double g,h;
    bool operator < (const abcd &x) const
    {
        return g + h < x.g + x.h ;
    }
};
struct Heap{
    abcd num;
    Heap *ls,*rs;
    void* operator new (size_t size,int pos,double g,double h);
    void operator delete (void* p);
}*root,*mempool,*C;
struct edge{
    int to,next;
    double f;
}table[400400];
int head[M],tot=1;
bool flag;
queue<void*> bin;
int n,m,k,ans,cnt[M];
double e,f[M];
void* Heap :: operator new (size_t size,int pos,double g,double h)
{
    if( !bin.empty() )
    {
        Heap *re=(Heap*)bin.front();
        bin.pop();
        re->num.pos=pos;
        re->num.g=g;
        re->num.h=h;
        re->ls=re->rs=0x0;
        return re;
    }
    if(C==mempool)
    {
        C=new Heap[1<<15];
        mempool=C+(1<<15);
    }
    C->num.pos=pos;
    C->num.g=g;
    C->num.h=h;
    C->ls=C->rs=0x0;
    return C++;
}
void Heap :: operator delete (void *p)
{
    bin.push(p);
}
Heap* Merge(Heap *x,Heap *y)
{
    if(!x) return y;
    if(!y) return x;
    if( y->num < x->num )
        swap(x,y);
    if(flag^=1)
        x->ls=Merge(x->ls,y);
    else
        x->rs=Merge(x->rs,y);
    return x;
}
inline void Insert(int pos,double g,double h)
{
    root=Merge(root,new (pos,g,h) Heap);
}
inline void Pop()
{
    delete root;
    root=Merge(root->ls,root->rs);
}
void Add(int x,int y,double z)
{
    table[++tot].to=y;
    table[tot].f=z;
    table[tot].next=head[x];
    head[x]=tot;
}
void SPFA()
{
    static int q[1<<16];
    static unsigned short r,h;
    static bool v[M];
    int i;
    memset(f,0x42,sizeof f);
    f[n]=0;q[++r]=n;
    while(r!=h)
    {
        int x=q[++h];v[x]=0;
        for(i=head[x];i;i=table[i].next)
            if( i&1 && f[table[i].to]>f[x]+table[i].f )
            {
                f[table[i].to]=f[x]+table[i].f;
                if(!v[table[i].to])
                    v[table[i].to]=1,q[++r]=table[i].to;
            }
    }
}
void A_Star()
{
    int i;
    k=static_cast<int>(e/f[1])+1;
    Insert(1,0,f[1]);
    while(root)
    {
        abcd x=root->num;Pop();
        if( ++cnt[x.pos]>k )
            continue;
        if(x.pos==n)
        {
            if(e-x.g<0) return ;
            e-=x.g;++ans;
            k=cnt[n]+static_cast<int>(e/x.g)+1;
        }
        for(i=head[x.pos];i;i=table[i].next)
            if(~i&1)
                Insert(table[i].to,x.g+table[i].f,f[table[i].to]);
    }
}
int main()
{
    int i,x,y;
    double z;
    cin>>n>>m>>e;
    for(i=1;i<=m;i++)
    {
        scanf("%d%d%lf",&x,&y,&z);
        Add(x,y,z);
        Add(y,x,z);
    }
    SPFA();
    A_Star();
    cout<<ans<<endl;
    return 0;
}
时间: 2024-10-12 19:05:56

BZOJ 1975 SDOI2010 魔法猪学院 A*k短路的相关文章

Bzoj 1975: [Sdoi2010]魔法猪学院 dijkstra,堆,A*,K短路

1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1357  Solved: 446[Submit][Status][Discuss] Description iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的:元素与元素之间可以互相转换:能量守恒……. 能量守恒……iPig 今

BZOJ 1975: [Sdoi2010]魔法猪学院 大水题 第k短路 spfa

https://www.lydsy.com/JudgeOnline/problem.php?id=1975 我好像到现在了第k短路都不会写,mdzz. 先spfa求出最短路,然后扫点存各种前置路径已经决定的最短路,小根堆暴力即可. 有向图要存反向边,写完才发现的,临时添成两种了,丑也没办法 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #

BZOJ 1975: [Sdoi2010]魔法猪学院

1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int duin,N,M,next[200010],point[5010],v[200010],next2[200010],point2[5010],v2[200010]; 7 double c[200010],c2[200010],dist[5010]

BZOJ 1975 魔法猪学院(K短路)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1975 题意:给出一个带权有向图.求一个最大的K使得前K短路的长度之和不大于给定的值Sum. 思路:首先,求出每个点到n的最短路.接着,使用优先队列,节点为(D,u).首先将(dis[1],1)进队.由于D在任意时候为一条1到n的路径的长度,那么对于边<u,v,w>,D-dis[u]+w+dis[v]为一条新的路径的长度. vector<pair<int,double>

[BZOJ1975][SDOI2010]魔法猪学院(k短路,A*)

1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 2748  Solved: 883[Submit][Status][Discuss] Description iPig 在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了 解:众所周知,世界是由元素构成的:元素与元素之间可以互相转换:能量守恒……. 能量守恒……iPig

洛谷 P2483 [SDOI2010]魔法猪学院

P2483 [SDOI2010]魔法猪学院 k短路模板 1 #include<queue> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=10005; 7 int n,m,s,t,k,num,head1[maxn*100],head2[maxn*100],tot; 8 int nxt1[maxn*100]

[K短路] SDOI2010 魔法猪学院

魔法猪学院 题目背景 感谢@kczno1 @X_o_r 提供hack数据 题目描述 iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的:元素与元素之间可以互相转换:能量守恒--. 能量守恒--iPig 今天就在进行一个麻烦的测验.iPig 在之前的学习中已经知道了很多种元素,并学会了可以转化这些元素的魔法,每种魔法需要消耗 iPig 一定的能量.作为 PKU 的顶尖

P2483 【模板】k短路([SDOI2010]魔法猪学院)

题目描述 iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的:元素与元素之间可以互相转换:能量守恒--. 能量守恒--iPig 今天就在进行一个麻烦的测验.iPig 在之前的学习中已经知道了很多种元素,并学会了可以转化这些元素的魔法,每种魔法需要消耗 iPig 一定的能量.作为 PKU 的顶尖学猪,让 iPig 用最少的能量完成从一种元素转换到另一种元素--等等,i

【k短路&amp;A*算法】BZOJ1975: [Sdoi2010]魔法猪学院

Description 找出1~k短路的长度. Solution k短路的求解要用到A*算法 A*算法的启发式函数f(n)=g(n)+h(n) g(n)是状态空间中搜索到n所花的实际代价 h(n)是n到结束状态最佳路径的估计代价 关于h(n)的选取,当h(n)<实际代价时,搜索慢但可出解:h(n)=实际代价时,正确率与效率最高:h(n)>实际代价,快但只能得到近似解. 但在k短路问题中,h(n)是可以选到准确值的,就是n到结束节点的最短路,预处理时从结束节点做一次单源最短路即可. 按广搜的方式