• 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
    ", Astar(s, t));
    112     }
    113     return 0;
    114 }
  • 相关阅读:
    MSXML应用总结
    MsXml创建和解析XML示例
    解决IAR无法跳转的问题
    总结4
    1012
    1010
    acm学习总结
    1005
    1004
    1006
  • 原文地址:https://www.cnblogs.com/usedrosee/p/4262396.html
Copyright © 2020-2023  润新知