problem
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 <= 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 M 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.
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.
Examples
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
题目大意: 给定n个点,在一般的基础上给每个点一个维度,也就是多了一个参数表示所在的层次,现在已知:
1、X层的点可以通过增加权值C到达X-1层或X+1层中的任何一个点 2、给定m个已经形成的路径
将层转换理解为虚点,N开双倍,2e5。
这里要注意虚点操作时,过渡的边应该这么建立: 1、因为X层的点 i 通过增加权值C才能到达X-1层或X+1层 所以sz[i].push_back(edge(t+n-1,c));和sz[i].push_back(edge(t+n+1,c)); 2、假设点 j 已经通过权值C到达X层,所以他可以到达X层所有点,即X层表示的虚点到X层的所有点的距离为0。所以sz[t+n].push_back(edge(i,0));
不要搞反了,这点很重要,因为涉及到你是否理解这题的虚点操作。
下面这个代码我为了省事,用cin,实际题面会T,用scanf或输入优化就可以过了。
#include <bits/stdc++.h> #pragma GCC optimize(2) using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; const int mod=1e9+7; const int maxn=2e5+7; struct edge{ int to,w; edge(int a,int b){ to=a; w=b; } }; vector<edge>sz[maxn]; int d[maxn],T,n,m,c; bool vis[maxn]; void spfa(){ memset(vis,0,sizeof(vis)); memset(d,inf,sizeof(d)); d[1]=0; vis[1]=1; queue<int>q; q.push(1); while(!q.empty()){ int t=q.front(); q.pop(); vis[t]=0; for(int i=0;i<sz[t].size();i++){ int y=sz[t][i].to; int x=sz[t][i].w; if(d[y]>d[t]+x){ d[y]=d[t]+x; if(!vis[y]){ vis[y]=1; q.push(y); } } } } } int main(){ cin>>T; for(int tt=1;tt<=T;tt++){ cin>>n>>m>>c; for(int i=1;i<=2*n;i++) sz[i].clear(); for(int i=1;i<=n;i++){ int t; cin>>t; sz[t+n].push_back(edge(i,0)); if(t>1) sz[i].push_back(edge(t+n-1,c)); if(t<n) sz[i].push_back(edge(t+n+1,c)); } for(int i=1;i<=m;i++){ int a,b,c; cin>>a>>b>>c; sz[a].push_back(edge(b,c)); sz[b].push_back(edge(a,c)); } spfa(); // for(int i=1;i<=n;i++) cout<<d[i]<<' '; // putchar('\n'); if(d[n]==inf) d[n]=-1; printf("Case #%d: %d\n",tt,d[n]); } } /* 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 Case #1: 2 Case #2: 3 */可以看其他人的题解:链接,还有图解
