zoukankan      html  css  js  c++  java
  • K短路(A*+SPFA)

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<queue>
      6 using namespace std;
      7 const int MAX_V = 1100;
      8 const int MAX_E = 110000;
      9 const int INF = 0x3f3f3f3f;
     10 
     11 struct ENode
     12 {
     13     int to;
     14     int w;
     15     int Next;
     16 };
     17 ENode edegs[MAX_E];
     18 ENode edegs1[MAX_E]; //存反图;
     19 int Head[MAX_V], Head1[MAX_V], tnt, tnt1;
     20 void Add_ENode (int a, int b, int w)
     21 {
     22     ++ tnt;
     23     edegs[tnt].to= b;
     24     edegs[tnt].w= w;
     25     edegs[tnt].Next= Head[a];
     26     Head[a]= tnt;
     27 //    ++ tnt;  //无向图
     28 //    edegs[tnt].to= a;
     29 //    edegs[tnt].w= w;
     30 //    edegs[tnt].Next= Head[b];
     31 //    Head[b]= tnt;
     32 }
     33 void Add_ENode1 (int a, int b, int w)
     34 {
     35     /**建反向图*/
     36     ++ tnt1;
     37     edegs1[tnt1].to= b;
     38     edegs1[tnt1].w= w;
     39     edegs1[tnt1].Next= Head1[a];
     40     Head1[a]= tnt1;
     41 //    ++ tnt1;  //无向图
     42 //    edegs1[tnt1].to= a;
     43 //    edegs1[tnt1].w= w;
     44 //    edegs1[tnt1].Next= Head1[b];
     45 //    Head1[b]= tnt1;
     46 }
     47 
     48 int Dis[MAX_V];
     49 bool visit[MAX_V]; //是否已经遍历过;
     50 int que[MAX_V]; // 模拟队列;
     51 int outque[MAX_V]; //记录每个点出队列的次数,防止有负边,保证无负边的图可以省略;
     52 bool SPFA(int s, int n)
     53 {
     54     /**SPFA处理反向图,预处理出Dis[]*/
     55     /*s:起点; n:点的总数*/
     56     int iq; //队列中元素个数;
     57     memset(Dis, INF, sizeof(Dis));
     58     memset(visit, false, sizeof(visit));
     59     memset(outque, 0, sizeof(outque));
     60     iq= 0;
     61     que[iq ++]= s;
     62     visit[s]= true;
     63     Dis[s]= 0;
     64     int i= 0;
     65     while (i< iq)
     66     {
     67         int u= que[i];
     68         visit[u]= false;
     69         outque[u] ++;
     70         if (outque[u]> n) return false; //当一个点进出队列超过n 次,必然有负边存在;
     71 
     72         for (int k= Head1[u]; k!= -1; k= edegs1[k].Next)
     73         {
     74             /*bfs,和Dijkstra相似*/
     75             int v= edegs1[k].to;
     76             if (Dis[v]> Dis[u]+ edegs1[k].w)
     77             {
     78                 Dis[v]= Dis[u]+ edegs1[k].w;
     79                 if (! visit[v])
     80                 {
     81                     visit[v]= true;
     82                     que[iq ++]= v;
     83                 }
     84             }
     85         }
     86         i ++;
     87     }
     88     return true;
     89 }
     90 
     91 struct Node
     92 {
     93     int from;
     94     int g; //g表示到当前点的路径长度
     95     int f; //f=g+dis dis表示当前点到终点的最短路径,即之前的预处理
     96     bool operator < (const Node &r) const
     97     {
     98         if (r.f== f) return r.g- g< 0;
     99         return r.f- f< 0;
    100     }
    101 };
    102 int A_star (int s, int t, int n, int k)
    103 {
    104     Node e, ne;
    105     int cnt= 0;
    106     priority_queue<Node> que;
    107     if (s== t) k ++;
    108     if (Dis[s]== INF) return -1;
    109     e.from= s;
    110     e.g= 0;
    111     e.f= e.g+ Dis[e.from];
    112     que.push(e);
    113     while (! que.empty())
    114     {
    115         e= que.top();
    116         que.pop();
    117         if (e.from== t) cnt ++;
    118         if (cnt== k) return e.g;
    119         for (int i= Head[e.from]; i!= -1; i= edegs[i].Next)
    120         {
    121             ne.from= edegs[i].to;
    122             ne.g= e.g+ edegs[i].w;
    123             ne.f= ne.g+ Dis[ne.from];
    124             que.push(ne);
    125         }
    126     }
    127     return -1;
    128 }
    129 
    130 void into()
    131 {
    132     /**初始化*/
    133     memset(Head,-1,sizeof(Head));
    134     memset(Head1,-1,sizeof(Head1));
    135     tnt= -1; tnt1= -1;
    136 }
    137 
    138 int main()
    139 {
    140     int n, m, k;
    141     int a, b, w;
    142     while (~ scanf("%d %d %d", &n, &m, &k))
    143     {
    144         into();
    145         for (int i= 0; i< m; i ++)
    146         {
    147             scanf("%d %d %d", &a, &b, &w);
    148             Add_ENode(a, b, w);
    149             Add_ENode1(b, a, w);  //建反图
    150         }
    151         SPFA(n, n); //处理出从终点到其他点的最短路径距离;
    152         int far= A_star(1, n, n, k);
    153         printf("%d
    ", far);
    154     }
    155     return 0;
    156 }
    View Code
  • 相关阅读:
    倍增算法2(树上倍增)
    倍增算法1
    可持久线段树
    【BZOJ】1059: [ZJOI2007]矩阵游戏(二分图匹配)
    【BZOJ】2743: [HEOI2012]采花(树状数组)
    【BZOJ】2959: 长跑(lct+缩点)(暂时弃坑)
    【学习笔记】LCT link cut tree
    【学习笔记】FFT
    【BZOJ】1001: [BeiJing2006]狼抓兔子(最小割 / 对偶图)
    【BZOJ】1007: [HNOI2008]水平可见直线(凸包)
  • 原文地址:https://www.cnblogs.com/Amaris-diana/p/11205523.html
Copyright © 2011-2022 走看看