• The Shortest Path in Nya Graph


    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

    思路:这题的难点主要在于如何去建图。如果我们每层只用一个点表示那是不可以的,为什么呢?因为这样的话你同楼层之间的点访问的花费都是0,可以自己模拟下

    所以我们采用用两个点来表示,一个是出,一个是入。

    N个点,然后有N层,要假如2*N个点。

    总共是3*N个点。

    点1~N就是对应的实际的点1~N.  要求的就是1到N的最短路。

    然后点N+1 ~ 3*N 是N层拆出出来的点。

    第i层,入边到N+2*i-1, 出边从N+2*i 出来。(1<= i <= N)

    N + 2*i    到  N + 2*(i+1)-1 加边长度为C. 表示从第i层到第j层。

    N + 2*(i+1) 到 N + 2*i - 1 加边长度为C,表示第i+1层到第j层。

    如果点i属于第u层,那么加边 i -> N + 2*u -1         N + 2*u ->i  长度都为0

    每一层的出点和该层的每个点相连,同时该层的每个点和这一层的入点相连。第i层的入点和i+1层的出点相连,i+1层的入点和第i层的出点相连

    可以用SPFA双端队列

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <queue>
      7 #include <set>
      8 #include <map>
      9 #include <string>
     10 #include <math.h>
     11 #include <stdlib.h>
     12 #include <time.h>
     13 using namespace std;
     14 
     15 #define INF 0x3f3f3f3f
     16 #define MAXN 1000100
     17 #define LL long long
     18 using namespace std;
     19 
     20 struct Edge{
     21     int to;
     22     int next;
     23     int val;
     24 }edge[MAXN];
     25 
     26 
     27 int res;
     28 int head[MAXN];
     29 int dist[MAXN];
     30 bool vis[MAXN];
     31 
     32 void init()
     33 {
     34     memset(head,-1, sizeof(head));
     35     res = 0;
     36 }
     37 
     38 void add(int u,int v,int w)
     39 {
     40     edge[res].to = v;
     41     edge[res].val = w;
     42     edge[res].next = head[u];
     43     head[u] = res++;
     44 }
     45 
     46 void SPFA(int n)
     47 {
     48     memset(vis,false,sizeof(vis));
     49     for (int i=1;i<=n;i++)
     50         dist[i]=INF;
     51     dist[1] = 0;
     52     vis[1] = true;
     53     deque<int > q;
     54     q.push_back(1);
     55     while (!q.empty())
     56     {
     57         int now = q.front();
     58         q.pop_front();
     59         vis[now] = false;
     60         for (int i=head[now];i!=-1;i=edge[i].next)
     61         {
     62             int v = edge[i].to;
     63             if (dist[v]>dist[now]+edge[i].val) {
     64                 dist[v] = dist[now] + edge[i].val;
     65                 if (!vis[v])
     66                 {
     67                     if (dist[v]<dist[q.front()])
     68                         q.push_front(v);
     69                     else
     70                         q.push_back(v);
     71                     vis[v] = true;
     72                 }
     73             }
     74         }
     75     }
     76 }
     77 
     78 
     79 
     80 int main()
     81 {
     82     int T,m,c,n;
     83     scanf("%d",&T);
     84     int t = 1;
     85     while (T--)
     86     {
     87         scanf("%d%d%d",&n,&m,&c);
     88         init();
     89         int u,v,w;
     90         for (int i=1;i<=n;i++) //同楼层
     91         {
     92             scanf("%d",&u);
     93             add(i,n+2*u-1,0);
     94             add(n+2*u,i,0);
     95         }
     96         for (int i=1;i<n;i++) // 不同楼层
     97         {
     98             add(n+2*i-1,n+2*(i+1),c);
     99             add(n+2*(i+1)-1,n+2*i,c);
    100         }
    101         while (m--)
    102         {
    103             scanf("%d%d%d",&u,&v,&w);
    104             add(u,v,w);
    105             add(v,u,w);
    106         }
    107         SPFA(3*n);
    108         if (dist[n] == INF)
    109             dist[n] = -1;
    110         printf("Case #%d: %d
    ",t++,dist[n]);
    111     }
    112     return 0;
    113 }

    这里推荐用Dj+优先队列

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <queue>
      7 #include <set>
      8 #include <map>
      9 #include <string>
     10 #include <math.h>
     11 #include <stdlib.h>
     12 #include <time.h>
     13 using namespace std;
     14 
     15 /*
     16  * 使用优先队列优化Dijkstra算法
     17  * 复杂度O(ElogE)
     18  * 注意对vector<Edge>E[MAXN]进行初始化后加边
     19  */
     20 const int INF=0x3f3f3f3f;
     21 const int MAXN=1000010;
     22 struct qnode
     23 {
     24     int v;
     25     int c;
     26     qnode(int _v=0,int _c=0):v(_v),c(_c){}
     27     bool operator <(const qnode &r)const
     28     {
     29         return c>r.c;
     30     }
     31 };
     32 struct Edge
     33 {
     34     int v,cost;
     35     Edge(int _v=0,int _cost=0):v(_v),cost(_cost){}
     36 };
     37 vector<Edge>E[MAXN];
     38 bool vis[MAXN];
     39 int dist[MAXN];
     40 void Dijkstra(int n,int start)//点的编号从1开始
     41 {
     42     memset(vis,false,sizeof(vis));
     43     for(int i=1;i<=n;i++)dist[i]=INF;
     44     priority_queue<qnode>que;
     45     while(!que.empty())que.pop();
     46     dist[start]=0;
     47     que.push(qnode(start,0));
     48     qnode tmp;
     49     while(!que.empty())
     50     {
     51         tmp=que.top();
     52         que.pop();
     53         int u=tmp.v;
     54         if(vis[u])continue;
     55         vis[u]=true;
     56         for(int i=0;i<E[u].size();i++)
     57         {
     58             int v=E[tmp.v][i].v;
     59             int cost=E[u][i].cost;
     60             if(!vis[v]&&dist[v]>dist[u]+cost)
     61             {
     62                 dist[v]=dist[u]+cost;
     63                 que.push(qnode(v,dist[v]));
     64             }
     65         }
     66     }
     67 }
     68 void addedge(int u,int v,int w)
     69 {
     70     E[u].push_back(Edge(v,w));
     71 }
     72 
     73 int main()
     74 {
     75     //freopen("in.txt","r",stdin);
     76     //freopen("out.txt","w",stdout);
     77     int T;
     78     int N,M,C;
     79     scanf("%d",&T);
     80     int iCase = 0;
     81     while(T--)
     82     {
     83         scanf("%d%d%d",&N,&M,&C);
     84         for(int i = 1;i <= 3*N;i++) E[i].clear();
     85         int u,v,w;
     86         for(int i = 1;i <= N;i++)
     87         {
     88             scanf("%d",&u);
     89             addedge(i,N + 2*u - 1,0);
     90             addedge(N + 2*u ,i,0);
     91 
     92         }
     93         for(int i = 1;i < N;i++)
     94         {
     95             addedge(N + 2*i-1,N + 2*(i+1),C);
     96             addedge(N + 2*(i+1)-1,N + 2*i,C);
     97         }
     98         while(M--)
     99         {
    100             scanf("%d%d%d",&u,&v,&w);
    101             addedge(u,v,w);
    102             addedge(v,u,w);
    103         }
    104         Dijkstra(3*N,1);
    105         iCase++;
    106         if(dist[N] == INF)dist[N] = -1;
    107         printf("Case #%d: %d
    ",iCase,dist[N]);
    108 
    109     }
    110     return 0;
    111 }
  • 相关阅读:
    版本控制之GitHub亲手实验总结
    Java的HashMap是如何实现的?
    Junit
    由swap引发的关于按值传递和引用传递的思考与总结
    C++了解free和delete
    GitHub使用教程
    Oracle下SQL学习笔记
    Flappy Bird
    尾递归与Continuation(转载)
    十步完全理解SQL(转载)
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/11299509.html
Copyright © 2020-2023  润新知