POJ 2449 Remmarguts' Date(第K短路 + A* + 最短路)题解

题意:找出第k短路,输出长度,没有输出-1

思路:这题可以用A*做。A*的原理是这样,我们用一个函数:f = g + h 来表示当前点的预期步数,f代表当前点的预期步数,g代表从起点走到当前的步数,h代表从当前点走到终点的最短路,显然h可以用最短路解出。那么我们从起点开始找,每次找f最小的点,直到找到第k个这样的点。

代码:

#include<queue>
#include<cstring>
#include<set>
#include<map>
#include<stack>
#include<string>
#include<cmath>
#include<vector>
#include<cstdio>
#include<iostream>
#include<algorithm>
typedef long long ll;
using namespace std;
const int maxn = 1000 + 10;
const int seed = 131;
const ll MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int n, m, k, tot;
struct Edge{
    int v, w, next;
}edge[maxn * 100];
struct As{
    int f, g, pos;
    bool operator < (const As a) const{
        return a.f == f? a.g < g : a.f < f;
    }
};
struct que{
    int u, v, w;
}q[100005];
int head[maxn], dis[maxn];
bool vis[maxn];
void init(){
    memset(head, -1, sizeof(head));
    tot = 0;
}
void addEdge(int u, int v, int w){
    edge[tot].v = v;
    edge[tot].w = w;
    edge[tot].next = head[u];
    head[u] = tot++;
}
void spfa(int st){
    for(int i = 0; i <= n; i++) dis[i] = INF;
    memset(vis, false, sizeof(vis));
    vis[st] = true;
    dis[st] = 0;
    queue<int> q;
    while(!q.empty()) q.pop();
    q.push(st);
    while(!q.empty()){
        int u = q.front();
        q.pop();
        vis[u] = false;
        for(int i = head[u]; i != -1; i = edge[i].next){
            int v = edge[i].v;
            int w = edge[i].w;
            if(dis[v] > dis[u] + w){
                dis[v] = dis[u] + w;
                if(!vis[v]){
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
}
int Astar(int st, int end){
   int cnt = 0;
   priority_queue<As> q;
   while(!q.empty()) q.pop();
   if(st == end) k++;
   if(dis[st] == INF) return -1;
   As a, b;
   a.pos = st, a.g = 0, a.f = a.g + dis[st];
   q.push(a);
   while(!q.empty()){
        a = q.top();
        q.pop();
        if(a.pos == end){
            cnt++;
            if(cnt == k) return a.f;
        }
        for(int i = head[a.pos]; i != -1; i = edge[i].next){
            b.pos = edge[i].v;
            b.g = a.g + edge[i].w;
            b.f = b.g + dis[b.pos];
            q.push(b);
        }
   }
   return -1;
}
int main(){
    while(~scanf("%d%d" ,&n, &m)){
        init();
        for(int i = 1; i <= m; i++){
            scanf("%d%d%d", &q[i].u, &q[i].v, &q[i].w);
            addEdge(q[i].v, q[i].u, q[i].w);
        }
        int s, t;
        scanf("%d%d%d", &s, &t, &k);
        spfa(t);
        init();
        for(int i = 1; i <= m; i++){
            addEdge(q[i].u, q[i].v, q[i].w);
        }
        printf("%d\n", Astar(s, t));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/KirinSB/p/9630632.html