Remmarguts'日付(POJ-2449)(永続的なヒープが解決することができます)

問題の説明

「良い男は女の子が任命を待つか、休憩作ることはありません!」オシドリの父は言いました。そっと彼の小さなアヒルの頭に触れ、彼は彼らに話をしました。 

「王子Remmargutsは彼の王国のUDFに住んでいる - 自由のユナイテッドデルタある日、彼らの隣国は、外交使節団にそれらプリンセスUyuwを送りました。。」 

「Erenow、王女は彼女が会場に来て、UDFと商業の会談を王子行けばと場合にのみ、とK番目の最短経路を経て彼女に会うことを彼に知らせる、Remmargutsに手紙を送った。(実際には、Uyuwにはありません「)すべてで来てほしいです 

貿易の発展と、このような素敵な女の子に興味を持っている、王子Remmargutsは本当に夢中になりました。彼はあなたを必要とする - 首相の助けを! 

DETAILS:UDFの首都はN局で構成されています。ステーションTは王子」現在の場所を表す番号ながらホールは、S番号付けされています。M泥が指示横には、ステーションの一部を接続します。王女を歓迎するRemmarguts'パスがさえ、それは本質的に異なると見なされる数SまたはTで同じ長さの異なるパスを持つステーションがあり、2倍以上2倍以下同じステーションが含まれる場合があります。 

入力

最初の行は、2つの整数の番号が含まれているNとM(1 <= N <= 1000、0 <= M <= 100000)。ステーションは、次のM行の各々は3つの整数の数値をA、BおよびT(1 <= A、B <= N、1 <= T <= 100)を含有する1からNまで番号が付けられています。これは、時間TとB番目のステーションにA番目局から導か側方があることを示しています 

最後の行は、3つの整数番号S、T及びK(1 <= S、T <= N、1 <= K <= 1000)からなります。

出力

単一の整数値からなる単一ライン:長さ(所要時間)歓迎プリンセスUyuwにK番目の最短パスを使用。K番目の最短経路が存在しない場合は、出力「-1」(引用符なし)が代わりにする必要があります。

サンプル入力

2 2
1 2 5
2 1 4
1 2 2

サンプル出力

14

問題の意味:有向グラフ所与は、次に開始点S nおよびmエッジ、端点Tと値k、TとSからk番目の質問経路の最短経路を与えます 

アイデア:kは、テンプレートのタイトルを短絡し、SPFA +は永続スタックを使用することができますが解決することができます

ソースプログラム

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<strinG>
#include<cstrinG>
#include<cmath>
#include<ctime>
#include<alGorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
#define Pair pair<int,int>
LL quickPow(LL a,LL b){ LL res=1; while(b){if(b&1)res*=a; a*=a; b>>=1;} return res; }
LL multMod(LL a,LL b,LL mod){ a%=mod; b%=mod; LL res=0; while(b){if(b&1)res=(res+a)%mod; a=(a<<=1)%mod; b>>=1; } return res%mod;}
LL quickMultPowMod(LL a, LL b,LL mod){ LL res=1,k=a; while(b){if((b&1))res=multMod(res,k,mod)%mod; k=multMod(k,k,mod)%mod; b>>=1;} return res%mod;}
LL quickPowMod(LL a,LL b,LL mod){ LL res=1; while(b){if(b&1)res=(a*res)%mod; a=(a*a)%mod; b>>=1; } return res; }
LL GetInv(LL a,LL mod){ return quickPowMod(a,mod-2,mod); }
LL GCD(LL x,LL y){ return !y?x:GCD(y,x%y); }
LL LCM(LL x,LL y){ return x/GCD(x,y)*y; }
const double EPS = 1E-6;
const int MOD = 1000000000+7;
const int N = 1500+5;
const int dx[] = {0,0,-1,1,1,-1,1,1};
const int dy[] = {1,-1,0,0,-1,1,-1,1};
using namespace std;

struct Node{
    int val,to;
    Node *left,*right;
    Node(){}
    Node(int val, int to, Node *left, Node *right) : val(val), to(to), left(left), right(right) {}
};
#define Limit 1000000
Node pool[Limit];
Node *top = pool;
Node *newNode(int val, int to) {
    if (top >= pool + Limit)
        return new Node(val, to, NULL, NULL);
    top->val = val;
    top->to = to;
    top->left = NULL;
    top->right = NULL;
    return top++;
}
Node *meGTe(Node *a, Node *b) {
    if (!a)
        return b;
    if (!b)
        return a;
    if (a->val > b->val)
        swap(a, b);
    Node *p = newNode(a->val, a->to);
    p->left = a->left;
    p->right = a->right;
    p->right = meGTe(p->right, b);
    swap(p->left, p->right);
    return p;
}
struct Status {
    int dist;
    Node *p;
    Status(){}
    Status(int dist, Node *p) : dist(dist), p(p) {}
    bool operator<(Status b) const { return dist > b.dist; }
};
struct Edge {
    int to, next;
    int w;
    Edge() {}
    Edge(int to, int next, int w) : to(to), next(next), w(w) {}
};
struct Map {
    int tot;
    int *head;
    Edge *edge;

    Map() {}
    Map(int n, int m) : tot(0) {
        head = new int[(n + 1)];
        edge = new Edge[(m + 5)];
        memset(head, 0, sizeof(int) * (n + 1));
    }
    void addEdge(int x, int y, int w) {
        edge[++tot].to = y;
        edge[tot].next = head[x];
        edge[tot].w = w;
        head[x] = tot;
    }
    Edge &operator[](int pos) { return edge[pos]; }
};
int n, m;
int s, t, k;
Map G, GT;
bool *vis;
int *dis, *pre;
queue<int> SPFA(int S) {
    vis = new bool[(n + 1)];
    dis = new int[(n + 1)];
    pre = new int[(n + 1)];

    memset(dis, INF, sizeof(int) * (n + 1));
    memset(vis, false, sizeof(bool) * (n + 1));

    queue<int> Q;
    Q.push(S);
    dis[S] = 0;
    pre[S] = 0;
    while (!Q.empty()) {
        int x = Q.front();
        Q.pop();
        vis[x] = false;
        for (int i = GT.head[x]; i; i = GT[i].next) {
            int y = GT[i].to;
            int w = GT[i].w;
            if (dis[x] + w < dis[y]) {
                dis[y] = dis[x] + w;
                pre[y] = i;
                if (!vis[y]) {
                    vis[y] = true;
                    Q.push(y);
                }
            }
        }
    }
    return Q;
}
Node **Hash;
void rebuild(queue<int> Q) { //建堆
    for (int i = 1; i <= n; i++) {
        for (int j = G.head[i]; j; j = G[j].next) {
            int to = G[j].to;
            if (pre[i] != j)
                G[j].w += dis[to] - dis[i];
        }
    }

    Hash = new Node *[(n + 1)];
    Q.push(t);
    Hash[t] = NULL;
    while (!Q.empty()) {
        int x = Q.front();
        Q.pop();
        if (pre[x])
            Hash[x] = Hash[G[pre[x]].to];
        for (int i = G.head[x]; i; i = G[i].next)
            if (pre[x] != i && dis[G[i].to] != INF)
                Hash[x] = meGTe(Hash[x], new Node(G[i].w, G[i].to, NULL, NULL));

        for (int i = GT.head[x]; i; i = GT[i].next) {
            int y = GT[i].to;
            if (pre[y] == i)
                Q.push(y);
        }
    }
}
int kthPath(int k) {
    if (s == t)
        k++;
    if (dis[s] == INF)
        return -1;
    if (k == 1)
        return dis[s];

    priority_queue<Status> Q;
    if (!Hash[s])
        return -1;

    Q.push(Status(Hash[s]->val, Hash[s]));
    while (--k && !Q.empty()) {
        Status x = Q.top();
        Q.pop();

        if (k == 1)
            return x.dist + dis[s];

        int y = x.p->to;
        if (Hash[y])
            Q.push(Status(x.dist + Hash[y]->val, Hash[y]));
        if (x.p->left)
            Q.push(Status(x.dist - x.p->val + x.p->left->val, x.p->left));
        if (x.p->right)
            Q.push(Status(x.dist - x.p->val + x.p->right->val, x.p->right));
    }
    return -1;
}
int main() {
    scanf("%d%d", &n, &m);
    G = Map(n, m);
    GT = Map(n, m);
    for (int i = 1, u, v, w; i <= m; i++) {
        scanf("%d%d%d", &u, &v, &w);
        G.addEdge(u, v, w);
        GT.addEdge(v, u, w);
    }
    scanf("%d%d%d", &s, &t, &k);
    queue<int> Q = SPFA(t);
    rebuild(Q);
    printf("%d\n", kthPath(k));
    return 0;
}

 

リリース1871元の記事 ウォンの賞賛702 ビュー194万+

おすすめ

転載: blog.csdn.net/u011815404/article/details/102521531