A*算法求K短路(POJ 2449 Remmarguts' Date)
静态链表实现图存储
#include
<
stdio.h
>
#include < string .h >
#include < queue >
#include < stack >
#include < vector >
using namespace std;
const int INF = 1e8;
const int NUMV = 1200 ; // number of vertex
const int NUME = 120010 ; // number of edge
int head[NUMV];
int ux[NUME], vx[NUME]; // edge: ux->vx
int next[NUME], cost[NUME];
int instk[NUMV]; // in stack or not
int dist[NUMV]; // shortest distance from dest to each vertex
int cnt[NUMV]; // count the times of a node out of queue
int n, m;
int s, t, k;
struct Node {
int f, g; // f = g + h
int v;
Node( int a, int b, int c):f(a),g(b),v(c){}
bool operator < ( const Node & a) const {
return a.f < f;
}
};
int spfa( int s, int t, int vx[]) {
stack < int > stk;
// initial instk[] and dist[]
for ( int i = 0 ; i <= n; ++ i) {
instk[i] = 0 ;
dist[i] = INF;
}
// push s into the stack
dist[s] = 0 ;
instk[s] = 1 ;
stk.push(s);
while ( ! stk.empty()) {
int cur = stk.top();
stk.pop();
instk[cur] = 0 ;
for ( int i = head[cur]; i >= 0 ; i = next[i]) {
if (dist[cur] + cost[i] < dist[vx[i]]) {
dist[vx[i]] = dist[cur] + cost[i];
if ( ! instk[vx[i]]) {
stk.push(vx[i]);
instk[vx[i]] = 1 ;
}
}
}
}
if (dist[t] == INF) return 0 ;
else return 1 ;
}
/*
int q[NUMV];
void Spfa(int s,int t, int vx[])
{
int i,u,v,l,r=0,tmp;
for(i=0;i<=n;++i)dist[i]=INF,instk[i]=0;
dist[s]=0;
q[r++]=s;
for(l=0;l<r;++l)
for(i=head[u=q[l]],instk[u]=0;i>=0;i=next[i])
if((tmp=dist[u]+cost[i])<dist[v=vx[i]])
{
dist[v]=tmp;
if(instk[v])continue;
instk[q[r++]=v]=1;
}
}
*/
int A_star( int s, int t, int vx[]) {
if (dist[s] >= INF) return - 1 ;
for ( int i = 0 ; i <= n; ++ i) cnt[i] = 0 ;
priority_queue < Node > nodeq;
nodeq.push(Node(dist[s], 0 ,s));
while ( ! nodeq.empty()) {
Node cur = nodeq.top();
nodeq.pop();
++ cnt[cur.v];
if (cnt[cur.v] > k) continue ;
if (cnt[t] == k) return cur.f;
for ( int i = head[cur.v]; i >= 0 ; i = next[i]) {
int g = cur.g + cost[i];
int f = g + dist[vx[i]];
int v = vx[i];
nodeq.push(Node(f,g,v));
}
}
return - 1 ;
}
int main( void )
{
while (scanf( " %d %d " , & n, & m) == 2 ) {
memset(head, - 1 , sizeof (head));
for ( int i = 0 ; i < m; ++ i) {
scanf( " %d %d %d " , ux + i, vx + i, cost + i);
next[i] = head[vx[i]];
head[vx[i]] = i;
}
scanf( " %d %d %d " , & s, & t, & k);
if (s == t) k += 1 ;
spfa(t, s, ux);
memset(head, - 1 , sizeof (head));
for ( int i = 0 ; i < m; ++ i) {
next[i] = head[ux[i]];
head[ux[i]] = i;
}
printf( " %d\n " , A_star(s, t, vx));
}
return 0 ;
}
#include < string .h >
#include < queue >
#include < stack >
#include < vector >
using namespace std;
const int INF = 1e8;
const int NUMV = 1200 ; // number of vertex
const int NUME = 120010 ; // number of edge
int head[NUMV];
int ux[NUME], vx[NUME]; // edge: ux->vx
int next[NUME], cost[NUME];
int instk[NUMV]; // in stack or not
int dist[NUMV]; // shortest distance from dest to each vertex
int cnt[NUMV]; // count the times of a node out of queue
int n, m;
int s, t, k;
struct Node {
int f, g; // f = g + h
int v;
Node( int a, int b, int c):f(a),g(b),v(c){}
bool operator < ( const Node & a) const {
return a.f < f;
}
};
int spfa( int s, int t, int vx[]) {
stack < int > stk;
// initial instk[] and dist[]
for ( int i = 0 ; i <= n; ++ i) {
instk[i] = 0 ;
dist[i] = INF;
}
// push s into the stack
dist[s] = 0 ;
instk[s] = 1 ;
stk.push(s);
while ( ! stk.empty()) {
int cur = stk.top();
stk.pop();
instk[cur] = 0 ;
for ( int i = head[cur]; i >= 0 ; i = next[i]) {
if (dist[cur] + cost[i] < dist[vx[i]]) {
dist[vx[i]] = dist[cur] + cost[i];
if ( ! instk[vx[i]]) {
stk.push(vx[i]);
instk[vx[i]] = 1 ;
}
}
}
}
if (dist[t] == INF) return 0 ;
else return 1 ;
}
/*
int q[NUMV];
void Spfa(int s,int t, int vx[])
{
int i,u,v,l,r=0,tmp;
for(i=0;i<=n;++i)dist[i]=INF,instk[i]=0;
dist[s]=0;
q[r++]=s;
for(l=0;l<r;++l)
for(i=head[u=q[l]],instk[u]=0;i>=0;i=next[i])
if((tmp=dist[u]+cost[i])<dist[v=vx[i]])
{
dist[v]=tmp;
if(instk[v])continue;
instk[q[r++]=v]=1;
}
}
*/
int A_star( int s, int t, int vx[]) {
if (dist[s] >= INF) return - 1 ;
for ( int i = 0 ; i <= n; ++ i) cnt[i] = 0 ;
priority_queue < Node > nodeq;
nodeq.push(Node(dist[s], 0 ,s));
while ( ! nodeq.empty()) {
Node cur = nodeq.top();
nodeq.pop();
++ cnt[cur.v];
if (cnt[cur.v] > k) continue ;
if (cnt[t] == k) return cur.f;
for ( int i = head[cur.v]; i >= 0 ; i = next[i]) {
int g = cur.g + cost[i];
int f = g + dist[vx[i]];
int v = vx[i];
nodeq.push(Node(f,g,v));
}
}
return - 1 ;
}
int main( void )
{
while (scanf( " %d %d " , & n, & m) == 2 ) {
memset(head, - 1 , sizeof (head));
for ( int i = 0 ; i < m; ++ i) {
scanf( " %d %d %d " , ux + i, vx + i, cost + i);
next[i] = head[vx[i]];
head[vx[i]] = i;
}
scanf( " %d %d %d " , & s, & t, & k);
if (s == t) k += 1 ;
spfa(t, s, ux);
memset(head, - 1 , sizeof (head));
for ( int i = 0 ; i < m; ++ i) {
next[i] = head[ux[i]];
head[ux[i]] = i;
}
printf( " %d\n " , A_star(s, t, vx));
}
return 0 ;
}
容器实现图存储
#include <stdio.h>
#include < string .h>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
const int INF = 1e8;
const int NUMV = 1010;
const int NUME = 100010;
struct Node {
int f, g;
int v;
Node ( int a, int b, int c):f(a),g(b),v(c) {}
bool operator < ( const Node& a) const {
return a.f < f;
}
};
struct Edge {
int u, v; // from u to v
int w; // cost
};
vector<Edge> edges;
vector< int > G[NUMV];
vector< int > iG[NUMV]; // inverse graph
int dist[NUMV]; // shotest distance
int instk[NUMV]; // in stack :spfa
int n, m;
int s, t, k;
void add_edge(vector< int > G[], int u, int v, int w) {
edges.push_back((Edge){u,v,w});
int m = edges.size();
G[u].push_back(m-1);
}
void spfa( int s, int t, vector< int > G[])
{
stack< int > stk;
for ( int i = 0; i < n; ++i) {
dist[i] = INF;
instk[i] = 0;
}
dist[s] = 0;
stk.push(s);
instk[s] = 1;
while (!stk.empty()) {
int u = stk.top();
stk.pop();
instk[u] = 0;
for ( int i = 0; i < G[u].size(); ++i) {
Edge& e = edges[G[u][i]];
if (dist[u]+e.w < dist[e.v]) {
dist[e.v] = dist[u]+e.w;
if (!instk[e.v]) {
stk.push(e.v);
instk[e.v] = 1;
}
}
}
}
}
int A_star( int s, int t, vector< int > G[]) {
if (dist[s] >= INF) return -1;
priority_queue<Node> nodeq;
nodeq.push(Node(dist[s], 0, s));
int cnt = 0;
while (!nodeq.empty()) {
Node cur = nodeq.top();
nodeq.pop();
if (cur.v == t) ++cnt;
if (cnt == k) return cur.f;
for ( int i = 0; i < G[cur.v].size(); ++i) {
Edge &e = edges[G[cur.v][i]];
int v = e.v;
int g = cur.g + e.w;
int f = g + dist[v];
nodeq.push(Node(f, g, v));
}
}
return -1;
}
void clear() {
for ( int i = 0; i < n; ++i) {
G[i].clear();
iG[i].clear();
}
edges.clear();
}
int main( void )
{
while (scanf("%d %d", &n, &m) == 2) {
for ( int i = 0; i < m; ++i) {
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
add_edge(G, u, v, w);
add_edge(iG, v, u, w);
}
scanf("%d %d %d", &s, &t, &k);
spfa(t, s, iG);
if (s == t) ++k;
printf("%d\n", A_star(s, t, G));
clear();
}
return 0;
}
#include < string .h>
#include <queue>
#include <stack>
#include <vector>
using namespace std;
const int INF = 1e8;
const int NUMV = 1010;
const int NUME = 100010;
struct Node {
int f, g;
int v;
Node ( int a, int b, int c):f(a),g(b),v(c) {}
bool operator < ( const Node& a) const {
return a.f < f;
}
};
struct Edge {
int u, v; // from u to v
int w; // cost
};
vector<Edge> edges;
vector< int > G[NUMV];
vector< int > iG[NUMV]; // inverse graph
int dist[NUMV]; // shotest distance
int instk[NUMV]; // in stack :spfa
int n, m;
int s, t, k;
void add_edge(vector< int > G[], int u, int v, int w) {
edges.push_back((Edge){u,v,w});
int m = edges.size();
G[u].push_back(m-1);
}
void spfa( int s, int t, vector< int > G[])
{
stack< int > stk;
for ( int i = 0; i < n; ++i) {
dist[i] = INF;
instk[i] = 0;
}
dist[s] = 0;
stk.push(s);
instk[s] = 1;
while (!stk.empty()) {
int u = stk.top();
stk.pop();
instk[u] = 0;
for ( int i = 0; i < G[u].size(); ++i) {
Edge& e = edges[G[u][i]];
if (dist[u]+e.w < dist[e.v]) {
dist[e.v] = dist[u]+e.w;
if (!instk[e.v]) {
stk.push(e.v);
instk[e.v] = 1;
}
}
}
}
}
int A_star( int s, int t, vector< int > G[]) {
if (dist[s] >= INF) return -1;
priority_queue<Node> nodeq;
nodeq.push(Node(dist[s], 0, s));
int cnt = 0;
while (!nodeq.empty()) {
Node cur = nodeq.top();
nodeq.pop();
if (cur.v == t) ++cnt;
if (cnt == k) return cur.f;
for ( int i = 0; i < G[cur.v].size(); ++i) {
Edge &e = edges[G[cur.v][i]];
int v = e.v;
int g = cur.g + e.w;
int f = g + dist[v];
nodeq.push(Node(f, g, v));
}
}
return -1;
}
void clear() {
for ( int i = 0; i < n; ++i) {
G[i].clear();
iG[i].clear();
}
edges.clear();
}
int main( void )
{
while (scanf("%d %d", &n, &m) == 2) {
for ( int i = 0; i < m; ++i) {
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
add_edge(G, u, v, w);
add_edge(iG, v, u, w);
}
scanf("%d %d %d", &s, &t, &k);
spfa(t, s, iG);
if (s == t) ++k;
printf("%d\n", A_star(s, t, G));
clear();
}
return 0;
}