POJ 2499 Remmarguts' Date (求第k短路模板题)

原题地址:http://poj.org/problem?id=2449

#include <cmath>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <set>
#include <cctype>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define MOD 1e9+7
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define CLR(x,y) memset((x),y,sizeof(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 2e5 + 5;
int u[maxn], v[maxn], w[maxn];
struct node {
    int v, w, nxt;
    bool operator <(const node &a)const {
        return w > a.w;
    }
    node() {}
    node(int a, int b): v(a), w(b) {}
} e[maxn];

int n, m, cnt, start, last, k;
int  head[maxn];
void init_head() {
    cnt = 0;
    memset(head, -1, sizeof(head));
}
void add_edge(int u, int v, int w) {
    e[++cnt].v = v;
    e[cnt].w = w;
    e[cnt].nxt = head[u];
    head[u] = cnt;
}
int vis[maxn], dis[maxn];
void dij(int num) {
    memset(dis, 0x3f, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    priority_queue<node>q;
    q.push(node(num, 0));
    dis[num] = 0;
    while(!q.empty()) {
        int u = q.top().v;
        q.pop();
        if(vis[u])  continue;
        vis[u] = 1;
        for(int i = head[u]; ~i; i = e[i].nxt) {
            int v = e[i].v;
            if(dis[v] > dis[u] + e[i].w) {
                dis[v] = dis[u] + e[i].w;
                q.push(node(v, dis[v]));
            }
        }
    }
}
struct AS {
    int u, g, h; //分别表示顶点,g是当前的精确值,h是估计值
    bool operator < (const AS & a)const {
        return g + h > a.g + a.h;
    }
    AS() {}
    AS(int u, int g, int h): u(u), g(g), h(h) {}
};
int ans;
void A_star() {
    int num = 0;
    ans = 0;
    if(start == last) k++; //如果起点和终点是同一个点,那么说明最短的就是0,所以可以加1了
    if(dis[start] == INF) {
        ans = -1;
        return;
    }
    priority_queue<AS>q;
    q.push(AS(start, 0, dis[start]));
    while(!q.empty()) {
        AS tmp = q.top();
        q.pop();
        if(tmp.u == last) num++;//如果到达说明离第k大距离又近了一步
        if(k == num) {//如果已经是最第k大最退出
            ans = tmp.g;
            return;
        }
        for(int i = head[tmp.u]; ~i; i = e[i].nxt) {
            int v = e[i].v;
            q.push(AS(v, tmp.g + e[i].w, dis[v]));
        }
    }
    ans = -1;//如果不存在第k大,就标记并退出
    return;
}
int main() {
    init_head();
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; i++) {
        scanf("%d%d%d", &u[i], &v[i], &w[i]);
        add_edge(v[i], u[i], w[i]);//反向建边求估计值
    }
    scanf("%d%d%d", &start, &last, &k);
    dij(last);
    init_head();//再次初始化建正向边
    for(int i = 1; i <= m; i++) {
        add_edge(u[i], v[i], w[i]);
    }
    A_star();
    printf("%d\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yiqzq/article/details/81290235
今日推荐