POJ 2449 Remmarguts' Date(第k短路+spfa+A*搜索)

来源:互联网 发布:mac 重装 u盘 编辑:程序博客网 时间:2024/06/04 23:30

题意:给出一个有向图,求出第k短路,节点可以重复经过。

思路:首先在反向边上进行一次spfa求出任一点至终点的最短距离,将这个距离作为A*搜索的h函数,估价函数f = g + h。注意这题有一个坑点,当起点和终点位于同一位置的时候,没经过任何边不算做一条路径。

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<iostream>#include<algorithm>#include<vector>#include<map>#include<queue>#include<stack>#include<string>#include<map>#include<set>#include<ctime>#define eps 1e-6#define LL long long#define pii pair<int, int>//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;const int MAXM = 100100;const int MAXN = 1010; const int INF = 0x3f3f3f3f;struct Edge {    int to, next, w;} edge[MAXM*2], edge2[MAXM*2];int head[MAXN], head2[MAXN], tot, tot2;int n, m;struct Node {int f, g, cur;Node(int f=0, int g=0, int v=0) : f(f), g(g), cur(v) {} bool operator < (const Node& A) const {return f==A.f ? g > A.g : f > A.f;}}; void addedge(int u,int v,int w) {    edge[tot].to = v;    edge[tot].w = w;    edge[tot].next = head[u];    head[u] = tot++;}void addedge2(int u,int v,int w) {    edge2[tot2].to = v;    edge2[tot2].w = w;    edge2[tot2].next = head2[u];    head2[u] = tot2++;}bool vis[MAXN]; //在队列标志int cnt[MAXN]; //每个点的入队列次数int dist[MAXN];bool spfa(int start, int n) {memset(vis, 0, sizeof(vis));for(int i = 1; i <= n; i++) dist[i] = INF;vis[start] = 1;dist[start] = 0;queue<int> q;while(!q.empty()) q.pop();q.push(start);memset(cnt, 0, sizeof(cnt));cnt[start] = 1;while(!q.empty()) {int u = q.front();q.pop();vis[u] = false;for(int i = head2[u]; i != -1; i = edge2[i].next) {Edge e = edge2[i];int v = e.to;if(dist[v] > dist[u]+e.w) {dist[v] = dist[u] + e.w;if(!vis[v]) {vis[v] = true;q.push(v);if(++cnt[v]>n) return false;}}}}return true;}  priority_queue<Node> q;void init() {    tot = tot2 = 0;    memset(head, -1, sizeof(head));    memset(head2, -1, sizeof(head2));    while(!q.empty()) q.pop();}int st, ed, k;int Astar() {if(dist[st] == INF) return -1;if(st == ed) k++;int cnt = 0;q.push(Node(dist[st], 0, st));while(!q.empty()) {Node t = q.top(); q.pop();int u = t.cur;if(u == ed) cnt++;if(cnt == k) return t.f;for(int i = head[u]; i !=  -1; i = edge[i].next) {int v = edge[i].to, w = edge[i].w;q.push(Node(t.g+w+dist[v], t.g+w, v));}}return -1;}int main() {    //freopen("input.txt", "r", stdin);while(cin >> n >> m) {init();for(int i = 1, u, v, d; i <= m; i++) {scanf("%d%d%d", &u, &v, &d);addedge(u, v, d);addedge2(v, u, d);}scanf("%d%d%d", &st, &ed, &k);spfa(ed, n);int ans = Astar();cout << ans << endl;}    return 0;}

0 0
原创粉丝点击