• HDU4725(KB4-P SPFA+LLL+SLF优化)


    The Shortest Path in Nya Graph

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 7981    Accepted Submission(s): 1794


    Problem Description

    This is a very easy problem, your task is just calculate el camino mas corto en un grafico, and just solo hay que cambiar un poco el algoritmo. If you do not understand a word of this paragraph, just move on.
    The Nya graph is an undirected graph with "layers". Each node in the graph belongs to a layer, there are N nodes in total.
    You can move from any node in layer x to any node in layer x + 1, with cost C, since the roads are bi-directional, moving from layer x + 1 to layer x is also allowed with the same cost.
    Besides, there are M extra edges, each connecting a pair of node u and v, with cost w.
    Help us calculate the shortest path from node 1 to node N.
     

    Input

    The first line has a number T (T <= 20) , indicating the number of test cases.
    For each test case, first line has three numbers N, M (0 <= N, M <= 105) and C(1 <= C <= 103), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers.
    The second line has N numbers li (1 <= li <= N), which is the layer of ith node belong to.
    Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 104), which means there is an extra edge, connecting a pair of node u and v, with cost w.
     

    Output

    For test case X, output "Case #X: " first, then output the minimum cost moving from node 1 to node N.
    If there are no solutions, output -1.
     

    Sample Input

    2 3 3 3 1 3 2 1 2 1 2 3 1 1 3 3 3 3 3 1 3 2 1 2 2 2 3 2 1 3 4
     

    Sample Output

    Case #1: 2 Case #2: 3
     

     

    Source

     
    SLF:Small Label First 策略,设要加入的节点是j,队首元素为i,若dist(j)<dist(i),则将j插入队首,否则插入队尾。
    LLL:Large Label Last 策略,设队首元素为i,队列中所有dist值的平均值为x,若dist(i)>x则将i插入到队尾,查找下一元素,直到找到某一i使得dist(i)<=x,则将i出队进行松弛操作。
     
    建图:
    相邻层之间建无向边,权值为c
    第i层向该层上的节点建有向边,权值为0
    节点i向其所在层的相邻层建有向边,权值为c。
    然后额外m条无向边。
      1 //2017-08-29
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <iostream>
      5 #include <algorithm>
      6 #include <queue>
      7 #include <stack>
      8 
      9 using namespace std;
     10 
     11 const int N = 300100;
     12 const int M = 2500100;
     13 const int INF = 0x3f3f3f3f;
     14 
     15 int head[N], tot;
     16 struct Edge{
     17     int to, next, w;
     18 }edge[M];
     19 
     20 void init(){
     21     tot = 0;
     22     memset(head, -1, sizeof(head));
     23 }
     24 
     25 void add_edge(int u, int v, int w){
     26     edge[tot].w = w;
     27     edge[tot].to = v;
     28     edge[tot].next = head[u];
     29     head[u] = tot++;
     30 }
     31 
     32 int n, m, c;
     33 bool vis[N];
     34 int dis[N], cnt[N];
     35 
     36 bool spfa(int s, int n){
     37     memset(vis, 0, sizeof(vis));
     38     memset(dis, INF, sizeof(dis));
     39     memset(cnt, 0, sizeof(cnt));
     40     vis[s] = 1;
     41     dis[s] = 0;
     42     cnt[s] = 1;
     43     deque<int> dq;
     44     dq.push_back(s);
     45     int sum = 0, len = 1;
     46     while(!dq.empty()){
     47         // LLL 优化
     48         while(dis[dq.front()]*len > sum){
     49             dq.push_back(dq.front());
     50             dq.pop_front();
     51         }
     52         int u = dq.front();
     53         sum -= dis[u];
     54         len--;
     55         dq.pop_front();
     56         vis[u] = 0;
     57         for(int i = head[u]; i != -1; i = edge[i].next){
     58             int v = edge[i].to;
     59             if(dis[v] > dis[u] + edge[i].w){
     60                 dis[v] = dis[u] + edge[i].w;
     61                 if(!vis[v]){
     62                     vis[v] = 1;
     63                     // SLF 优化
     64                     if(!dq.empty() && dis[v] < dis[dq.front()])
     65                       dq.push_front(v);
     66                     else dq.push_back(v);
     67                     sum += dis[v];
     68                     len++;
     69                     if(++cnt[v] > n)return false;
     70                 }
     71             }
     72         }
     73     }
     74     return true;
     75 }
     76 
     77 bool book[N];
     78 int layer[N];
     79 
     80 int main()
     81 {
     82     //freopen("inputP.txt", "r", stdin);
     83     int T, kase = 0;
     84     scanf("%d", &T);
     85     while(T--){
     86         scanf("%d%d%d", &n, &m, &c);
     87         init();
     88         memset(book, 0, sizeof(book));
     89         for(int i = 1; i <= n; i++){
     90             scanf("%d", &layer[i]);
     91             book[layer[i]] = 1;
     92         }
     93         for(int i = 1; i <= n; i++){
     94             add_edge(n+layer[i], i, 0);
     95             if(layer[i] > 1 && book[layer[i]-1])
     96                   add_edge(i, n+layer[i]-1, c);
     97             if(layer[i] < n && book[layer[i]+1])
     98                   add_edge(i, n+layer[i]+1, c);
     99         }
    100         for(int i = 1; i < N; i++)
    101           if(book[i] && book[i+1]){
    102               add_edge(i+n, i+1+n, c);
    103               add_edge(i+1+n, i+n, c);
    104           }
    105         int u, v, w;
    106         while(m--){
    107             scanf("%d%d%d", &u, &v, &w);
    108             add_edge(u, v, w);
    109             add_edge(v, u, w);
    110         }
    111         spfa(1, n<<1);
    112         printf("Case #%d: %d
    ", ++kase, dis[n]==INF?-1:dis[n]);
    113     }
    114 
    115     return 0;
    116 }
  • 相关阅读:
    面试试题
    使用NSURLSessionDataTask请求数据(get post方式)
    使用SSZipArchive第三方库解压zip包
    实现图文混编界面
    使用多线程创建单例对象
    SQL语句的种类_外键_表连接(内连接和左外连接)
    使用第三方库(FMDB) 本地数据库存储数据 --使用为了保证线程安全做法
    利用第三方库XML解析 (TBXML)转化成模型数据
    蓝牙传送_多点连接 (适用于>iOS7)
    Unity 产生各不相同的随机数
  • 原文地址:https://www.cnblogs.com/Penn000/p/7448832.html
Copyright © 2020-2023  润新知