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\n",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\n",iCase,dist[N]); 108 109 } 110 return 0; 111 }