zoukankan      html  css  js  c++  java
  • HDU

    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.

    InputThe 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 <= 10 5) and C(1 <= C <= 10 3), which is the number of nodes, the number of extra edges and cost of moving between adjacent layers.
    The second line has N numbers l i (1 <= l i <= N), which is the layer of i th node belong to.
    Then come N lines each with 3 numbers, u, v (1 <= u, v < =N, u <> v) and w (1 <= w <= 10 4), which means there is an extra edge, connecting a pair of node u and v, with cost w.OutputFor 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

    这题的难点是层数的处理,有两种处理方法。
    一种是仔细想可以想到的,用vector把每层的点存下来,在djkstra松弛操作的同时,对当前点的相邻两层点全部松弛一遍(具体看代码)。
    第二种应该是正解,就是拆点。其实上一种也相当于拆点,只不过拆很暴力,不够彻底。
    我们可以把层当做一个新的点,在该层的点到该层的距离为0,该层到相邻层的距离为c。但因为同层的点不一定相互联通,所以要把一个层分为两个点,一个入口点,一个出口点,入口点和出口点之间不联通。
    法一ac代码:
      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cmath>
      6 #include <queue>
      7 using namespace std;
      8 typedef long long ll;
      9 const int inf = 0x3f3f3f3f;
     10 const int maxn = 1e5 + 10;
     11 int n, m, c;
     12 int pos[maxn];
     13 vector<int> laye[maxn];
     14 int head[maxn];
     15 int d[maxn];
     16 bool vis[maxn];
     17 bool visi[maxn];
     18 struct edge{
     19     int to, nex, cost;
     20 }eg[2 * maxn];
     21 int cnt = 0;
     22 inline void add(int u,int v,int cost) {
     23     eg[cnt].to = v;
     24     eg[cnt].nex = head[u];
     25     eg[cnt].cost = cost;
     26     head[u] = cnt++;
     27 }
     28 struct Rule {
     29     bool operator () (int &a,int &b) const {
     30         return d[a] > d[b];
     31     }
     32 };
     33 inline void dijkstra(int s) {
     34     memset(vis, 0, sizeof(vis));
     35     memset(d, inf, sizeof(d));
     36     priority_queue<int, vector<int>, Rule> q;
     37     d[s] = 0;
     38     q.push(s);
     39     while(!q.empty()) {
     40         int u = q.top(); q.pop();
     41         for(int k = head[u]; ~k; k = eg[k].nex) {
     42             int v = eg[k].to;
     43             if(d[v] > d[u] + eg[k].cost) {
     44                 //    printf("%d %d %d
    ", u, v,eg[k].cost);
     45                 d[v] = d[u] + eg[k].cost;
     46                 q.push(v);
     47             }
     48         }
     49         if(pos[u] < n && !vis[pos[u]+ 1]) {
     50             vis[pos[u] +  1] = true;        //注意标记层数,不然会超时
     51             for(int i = 0; i < laye[pos[u] + 1].size(); ++i) {
     52                 int v = laye[pos[u] + 1][i];
     53                 if(d[v] > d[u] + c) {
     54                     //               printf("%d %d %d
    ", u, v,c);
     55                     d[v] = d[u] + c;
     56                     q.push(v);
     57                     
     58                 }
     59             }
     60         }
     61         if(pos[u]  > 1 && !vis[pos[u] - 1]) {
     62             vis[pos[u] -  1] = true;
     63             for(int i = 0; i < laye[pos[u] - 1].size(); ++i) {
     64                 int v = laye[pos[u] - 1][i];
     65                 if(d[v] > d[u] + c) {
     66                     //             printf("%d %d %d
    ", u, v,c);
     67                     d[v] = d[u] + c;
     68                     q.push(v);
     69                     
     70                 }
     71             }
     72         }
     73     }
     74 }
     75 int main()
     76 {
     77     int t;
     78     scanf("%d", &t);
     79     for(int cas = 1; cas <= t; ++cas) {
     80         cnt = 0;
     81         memset(head, -1, sizeof(head));
     82         memset(pos, 0, sizeof(pos));
     83         
     84         scanf("%d %d %d", &n, &m, &c);
     85         int u, v, cost;
     86         for(int i = 1; i <= n; ++i) {
     87             scanf("%d", &u);
     88             pos[i] = u;
     89             laye[u].push_back(i);
     90         }
     91         for(int i =0; i < m; ++i) {
     92             scanf("%d %d %d", &u, &v, &cost);
     93             add(u, v, cost);
     94             add(v, u, cost);
     95         }
     96         
     97         dijkstra(1);
     98         if(d[n] == inf || n == 0)
     99             printf("Case #%d: -1
    ", cas);
    100         else
    101             printf("Case #%d: %d
    ", cas, d[n]);
    102         for(int i = 1; i <= n; ++i) laye[i].clear();
    103     }
    104     return 0;
    105 }
    View Code

    法二代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <queue>
     7 using namespace std;
     8 typedef long long ll;
     9 const int inf = 0x3f3f3f3f;
    10 const int maxn = 5 * 1e5;
    11 int n, m, c;
    12 int pos[maxn];
    13 vector<int> laye[maxn];
    14 int head[maxn];
    15 int d[maxn];
    16 bool vis[maxn];
    17 struct edge{
    18     int to, nex, cost;
    19 }eg[maxn];
    20 int cnt = 0;
    21 void add(int u,int v,int cost) {
    22     eg[cnt].to = v;
    23     eg[cnt].nex = head[u];
    24     eg[cnt].cost = cost;
    25     head[u] = cnt++;
    26 }
    27 struct Rule {
    28     bool operator () (int a,int b) const {
    29         return d[a] > d[b];
    30     }
    31 };
    32 void dijkstra(int s) {
    33     memset(d, inf, sizeof(d));
    34     priority_queue<int, vector<int>, Rule> q;
    35     d[s] = 0;
    36     q.push(s);
    37     while(!q.empty()) {
    38         int u = q.top(); q.pop();
    39         for(int k = head[u]; k != -1; k = eg[k].nex) {
    40             int v = eg[k].to;
    41             if(d[v] > d[u] + eg[k].cost) {
    42                 //   printf("%d %d %d
    ", u, v,eg[k].cost);
    43                 d[v] = d[u] + eg[k].cost;
    44                 q.push(v);
    45             }
    46             
    47         }
    48     }
    49 }
    50 int main()
    51 {
    52     int t;
    53     scanf("%d", &t);
    54     for(int cas = 1; cas <= t; ++cas) {
    55         
    56         cnt = 0;
    57         memset(d, inf, sizeof(d));
    58         memset(head, -1, sizeof(head));
    59         memset(pos, 0, sizeof(pos));
    60         scanf("%d %d %d", &n, &m, &c);
    61         int u, v, cost;
    62         for(int i = 1; i <= n; ++i) {
    63             scanf("%d", &u);
    64             pos[i] = u;
    65             add(i, n + 2 * u - 1, 0);//层内的点到该层距离为0
    66             add(n + 2 * u, i, 0);
    67             vis[u] = true;
    68         }
    69         for(int i = 1; i < n; ++i) {
    70             if(vis[i] && vis[i + 1]) {//这个似乎不加也行
    71                 add(n + 2 * i - 1, n + 2 * (i + 1), c);//相邻层之间的距离为c
    72                 add(n + 2 * (i + 1) - 1, n + 2 * i, c);
    73             }
    74         }
    75         for(int i =0; i < m; ++i) {
    76             scanf("%d %d %d", &u, &v, &cost);
    77             add(u, v, cost);
    78             add(v, u, cost);
    79         }
    80         
    81         dijkstra(1);
    82         if(d[n] == inf || n == 0)
    83             printf("Case #%d: -1
    ", cas);
    84         else
    85             printf("Case #%d: %d
    ", cas, d[n]);
    86     }
    87     return 0;
    88 }
    View Code
  • 相关阅读:
    中间人攻击
    RSA算法详解
    Scala的自定义类型标记
    新版gitbook导出pdf
    request中跟路径有关的api的分析
    struts2初始化探索(一)
    struts2入门教学
    区块链学习笔记(五)
    区块链学习笔记(四)
    区块链学习笔记(三)
  • 原文地址:https://www.cnblogs.com/zmin/p/8806633.html
Copyright © 2011-2022 走看看