Fellow me on GitHub

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\n", ++kase, dis[n]==INF?-1:dis[n]);
113     }
114 
115     return 0;
116 }

 

posted @ 2017-08-29 16:14  Penn000  阅读(269)  评论(0编辑  收藏  举报