poj 2449

转自http://blog.csdn.net/sdj222555/article/details/7690081

 

题目大意就是给出一个图,然后给出一个起点个一个终点,求这两点间的第K短路。

本题中是可以走重复的路的,所以如果一张图中有一个环的话,无论求第几短路都是存在的。

 

网上大部分的方法都是用A* + 最短路的方法做的。  

对于A* ,估价函数 = 当前值+当前位置到终点的距离,即 F(p)=g(p)+h(p),每次扩展估价函数值中最小的一个。对于k短路来说,g(p)为当前从s到p所走的长度,h(p)为从p到 t 的最短路的长度,则F(p)的意义就是从s按照当前路径走到 p 后要走到终点 t 一共至少要走多远。也就是说我们每次的扩展都是有方向的扩展,这样就可以提高求解速度和降低扩展的状态数目。为了加速计算,h(p)需要从A*搜索之前进行预处理,只要将原图的所有边反向,再从终点 t 做一次单源最短路径就可以得到每个点的h(p)了。

在下面这个代码中

A结构体中,v代表的是当前走到的点,f和g分别为f函数和g函数的值,每次优先搜的是f函数较小的。这样就能保证搜索出来的一定是第K小短路,并且避免了一定的不必要计算。

 

  1 #include <iostream>

  2 #include <cstring>

  3 #include <cstdlib>

  4 #include <cstdio>

  5 #include <queue>

  6 #define MAXN 1005

  7 #define MAXM 500005

  8 #define INF 1000000000

  9 using namespace std;

 10 struct node

 11 {

 12     int v, w, next;

 13 }edge[MAXM], revedge[MAXM];

 14 struct A

 15 {

 16     int f, g, v;

 17     bool operator <(const A a)const {

 18         if (a.f == f) return a.g < g;

 19         return a.f < f;

 20     }

 21 };

 22 int e, vis[MAXN], d[MAXN], q[MAXM * 5];

 23 int head[MAXN], revhead[MAXN];

 24 int n, m, s, t, k;

 25 void init()

 26 {

 27     e = 0;

 28     memset(head, -1, sizeof(head));

 29     memset(revhead, -1, sizeof(revhead));

 30 }

 31 void insert(int x, int y, int w)

 32 {

 33     edge[e].v = y;

 34     edge[e].w = w;

 35     edge[e].next = head[x];

 36     head[x] = e;

 37     revedge[e].v = x;

 38     revedge[e].w = w;

 39     revedge[e].next = revhead[y];

 40     revhead[y] = e++;

 41 }

 42 void spfa(int src)

 43 {

 44     for (int i = 1; i <= n; i++) d[i] = INF;

 45     memset(vis, 0, sizeof(vis));

 46     vis[src] = 0;

 47     int h = 0, t = 1;

 48     q[0] = src;

 49     d[src] = 0;

 50     while (h < t)

 51     {

 52         int u = q[h++];

 53         vis[u] = 0;

 54         for (int i = revhead[u]; i != -1; i = revedge[i].next)

 55         {

 56             int v = revedge[i].v;

 57             int w = revedge[i].w;

 58             if (d[v] > d[u] + w)

 59             {

 60                 d[v] = d[u] + w;

 61                 if (!vis[v])

 62                 {

 63                     q[t++] = v;

 64                     vis[v] = 1;

 65                 }

 66             }

 67         }

 68     }

 69 }

 70 int Astar(int src, int des)

 71 {

 72     int cnt = 0;

 73     priority_queue<A>Q;

 74     if (src == des) k++;

 75     if (d[src] == INF) return -1;

 76     A t, tt;

 77     t.v = src, t.g = 0, t.f = t.g + d[src];

 78     Q.push(t);

 79     while (!Q.empty())

 80     {

 81         tt = Q.top();

 82         Q.pop();

 83         if (tt.v == des)

 84         {

 85             cnt++;

 86             if (cnt == k) return tt.g;

 87         }

 88         for (int i = head[tt.v]; i != -1; i = edge[i].next)

 89         {

 90             t.v = edge[i].v;

 91             t.g = tt.g + edge[i].w;

 92             t.f = t.g + d[t.v];

 93             Q.push(t);

 94         }

 95     }

 96     return -1;

 97 }

 98 int main()

 99 {

100     int x, y, w;

101     while (scanf("%d%d", &n, &m) != EOF)

102     {

103         init();

104         for (int i = 1; i <= m; i++)

105         {

106             scanf("%d%d%d", &x, &y, &w);

107             insert(x, y, w);

108         }

109         scanf("%d%d%d", &s, &t, &k);

110         spfa(t);

111         printf("%d\n", Astar(s, t));

112     }

113     return 0;

114 }

 

你可能感兴趣的:(poj)