首页 > 代码库 > BZOJ 1975 SDOI 2010 魔法猪学院 A*求K短路

BZOJ 1975 SDOI 2010 魔法猪学院 A*求K短路

题目大意:给出一张无向图,给出一个数值m,求出从1到N的前k短路的长度和>=数值m。


思路:注意!不能使用priority_queue,否则你会死的很惨。。为了解惑,我去找了当年SD省选的原题,分明空间是256M,为什么BZOJ和BASHUOJ上都是64M??卡pq有意思么???

思路很简单,就是按顺序求出这张图的前k短路,然后当m减成负数的时候就返回。


CODE:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 400010
#define MAXP 5010
using namespace std;
 
struct Complex{
    double g,h;
    int pos;
     
    Complex(double _,double __,int ___):g(_),h(__),pos(___) {}
    bool operator <(const Complex &a)const {
        return g + h > a.g + a.h;
    }
}now(0,0,0);
 
int points,edges;
double ceil;
 
int head[MAXP],tail[MAXP],total;
int next[MAX],aim[MAX];
double length[MAX];
 
double f[MAXP];
bool v[MAXP];
int cnt[MAXP];
 
inline void Add(int x,int y,double len)
{
    next[++total] = head[x];
    aim[total] = y;
    length[total] = len;
    head[x] = total;
    next[++total] = tail[y];
    aim[total] = x;
    length[total] = len;
    tail[y] = total;
}
 
void SPFA()
{
    static queue<int> q;
    while(!q.empty())   q.pop();
    memset(f,0x43,sizeof(f));
    f[points] = .0;
    q.push(points);
    while(!q.empty()) {
        int x = q.front(); q.pop();
        v[x] = false;
        for(int i = tail[x]; i; i = next[i])
            if(f[aim[i]] > f[x] + length[i]) {
                f[aim[i]] = f[x] + length[i];
                if(!v[aim[i]])
                    v[aim[i]] = true,q.push(aim[i]); 
            }
    }
}
 
int Astar(int k)
{
    static priority_queue<Complex> q;
    now = Complex(.0,f[1],1);
    q.push(now);
    while(!q.empty()) {
        now = q.top(); q.pop();
        if(++cnt[now.pos] > k)   continue;
        if(now.pos == points) {
            if(ceil -= now.g,ceil <= 0)
                return cnt[now.pos] - 1;
            k = cnt[points] + static_cast<int>(ceil / now.g) + 1;
        }
        for(int i = head[now.pos]; i; i = next[i])
            if(cnt[aim[i]] <= k)
                q.push(Complex(now.g + length[i],f[aim[i]],aim[i]));
    }
    return 0;
}
 
int main()
{
    cin >> points >> edges >> ceil;
    for(int x,y,i = 1; i <= edges; ++i) {
        double len;
        scanf("%d%d%lf",&x,&y,&len);
        Add(x,y,len);
    }
    SPFA();
    cout << Astar(static_cast<int>(ceil / f[1]) + 1) << endl;
    return 0;
}


BZOJ 1975 SDOI 2010 魔法猪学院 A*求K短路