[BZOJ 1975][Sdoi2010]魔法豬學院

K短路,左偏樹,A*

其中st是用來比較的估價函數,此估價函數是完全準確的,ed是實際走過的路程

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define maxn 5010
#define M 200010
using namespace std;

int n, m, ans;
double tot, dis[maxn];
const double inf = 1e12;
bool vis[maxn];

struct Node{
    double st, ed;
    int l, r, am, dis;
    bool operator<(const Node& k)const{
        return st > k.st;
    }
    Node(double _ = 0, double __ = 0, int val = 0, int l = 0, int r = 0, int dis = 0):
        st(_), ed(__), am(val), l(l), r(r), dis(dis){}
};
Node T[1850010];
int root, size;

int merge(int a, int b){
    if(!a || !b)return a + b;
    if(T[a] < T[b])swap(a, b);
    T[a].r = merge(T[a].r, b);
    if(T[T[a].l].dis < T[T[a].r].dis)
        swap(T[a].l, T[a].r);
    T[a].dis = T[a].r ? T[T[a].r].dis + 1 : 0;
    return a;
}
Node TMP;
void Get_pop(){
    TMP = T[root];
    root = merge(T[root].l, T[root].r);
}

queue<int>Q;

struct solver{
    int h[maxn], cnt;
    int nxt[M], to[M];
    double w[M];
    void add(int u, int v, double d){
        cnt ++;
        to[cnt] = v;
        w[cnt] = d;
        nxt[cnt] = h[u];
        h[u] = cnt;
    }

    void Spfa(){
        for(int i = 1; i <= n; i ++)dis[i] = inf;
        Q.push(n);dis[n] = 0;
        while(!Q.empty()){
            int u = Q.front();Q.pop();
            for(int i = h[u]; i; i = nxt[i]){
                int v = to[i];
                if(dis[v] > dis[u] + w[i]){
                    dis[v] = dis[u] + w[i];
                    if(!vis[v]){
                        vis[v] = true;
                        Q.push(v);
                    }
                }
            }vis[u] = false;
        }
    }

    void Astar(){
        T[++ size] = Node(dis[1], 0, 1);root = size;
        while(true){
            Get_pop();int u = TMP.am;
            for(int i = h[u]; i; i = nxt[i]){
                int v = to[i];
                T[++ size] = Node(TMP.ed + w[i] + dis[v], TMP.ed + w[i], v);
                root = merge(root, size);
            }

            if(u == n){
                tot -= TMP.ed;
                if(tot < 0)return;
                ans ++;
            }
        }
    }
}G0, G1;

int main(){
#ifndef ONLINE_JUDGE
    freopen("magic.in", "r", stdin);
    freopen("magic.out", "w", stdout);
#endif
    scanf("%d%d%lf", &n, &m, &tot);
    int u, v; double w;
    for(int i = 1; i <= m; i ++){
        scanf("%d%d%lf", &u, &v, &w);
        G0.add(u, v, w), G1.add(v, u, w);
    }
    G1.Spfa();
    G0.Astar();
    printf("%d\n", ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章