第K短路径 POJ 2449

第K短路径 POJ 2449

一个朴实的算法是搜索出所有的路径,去第k短。

然后我们尝试能否让第一次到底的最短路径,第二次到达的第二短。其实是给A*。
我们维护已经走了多远和距离终点还有多远的距离和小的优先走,就能达到上述要求。
距离终点还有多远反向建图,求一次最短路即可。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>

using namespace std;
const int MAXN = 1050;
const int MAXM = 1e5 + 10;

int n, m, first[MAXN], sign;

int dist[MAXN], S, T, K;

struct Edge {
    int to, w, next;
} edge[MAXM * 4];

void init() {
    memset(first, -1, sizeof(first));
    sign = 0;
}

void add_edge(int u, int v, int w) {
    edge[sign].to = v;
    edge[sign].w = w;
    edge[sign].next = first[u];
    first[u] = sign++;
}

struct Input {
    int u, v, w;
} in[MAXM];

struct PriNode {
    int to, cost;
    PriNode(int tt = 0, int cc = 0):to(tt), cost(cc) {}
    friend bool operator < (const PriNode &a, const PriNode &b) {
        return a.cost > b.cost;
    }
};

void dijkstra(int s) {
    priority_queue<PriNode>que;
    que.push(PriNode(s, 0));
    memset(dist, -1, sizeof(dist));
    while(!que.empty()) {
        PriNode now = que.top();
        que.pop();
        if(dist[now.to] == -1) {
            dist[now.to] = now.cost;
            for(int i = first[now.to]; ~i; i = edge[i].next) {
                int to = edge[i].to, w = edge[i].w;
                if(dist[to] == -1) {
                    que.push(PriNode(to, now.cost + w));
                }
            }
        }
    }
}

struct Node {
    int to, val;
    Node(int tt = 0, int vv = 0):to(tt), val(vv) {}
    friend bool operator < (const Node &a, const Node &b) {
        return a.val + dist[a.to] > b.val + dist[b.to];
    }
};

int a_start(int S, int T, int K) {
    priority_queue<Node>que;
    que.push(Node(S, 0));
    while(!que.empty()) {
        Node now = que.top();
        que.pop();
        if(now.to == T) {
            if(K > 1) {
                K--;
            } else {
                return now.val;
            }
        }
        for(int i = first[now.to]; ~i; i = edge[i].next) {
            int to = edge[i].to, w = edge[i].w;
            que.push(Node(edge[i].to, now.val + w));
        }
    }
    return -1;
}

int main() {
    init();
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= m; i++ ) {
        scanf("%d %d %d", &in[i].u, &in[i].v, &in[i].w);
        add_edge(in[i].v, in[i].u, in[i].w);
    }
    scanf("%d %d %d", &S, &T, &K);
    dijkstra(T);
    if(dist[S] == -1) {
        puts("-1");
        return 0;
    }
    if(S == T) {
        K++;
    }
    init();
    for(int i = 1; i <= m; i++ ) {
        add_edge(in[i].u, in[i].v, in[i].w);
    }
    printf("%d\n", a_start(S, T, K));
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Q1143316492/p/9623456.html