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; }