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.
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 <= 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.
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
题意:有n个点,编号为 1 ~ n,每一个点都位于一个层面,第 x 层上的任意一点 到 第 x + 1 层的任意一点花费为 C,此外还有m条给定起点终点边权的边。问 从点 1 到 点 n 的最小花费
思路: 主要是建图的问题。如果暴力建图,大概复杂度是 20 * 3e7,给定时限是 1s,直接GG。这里就需要技巧建图。
设每一层都是一个点,对于第 i 层,其编号是 n + i,对第 i 层的所有点,都连接 从 层 到 点的单向边,边权为0。对于相邻的两个层 x 和 x + 1,连接 x 层上所有点到 x + 1层的单向边,边权为 C, 连接 x + 1上所有的点 到 x 层的单向边,边权为C。
AC代码:
#include<bits/stdc++.h>
#define debug(x) cout << "[" << #x <<": " << (x) <<"]"<< endl
#define pii pair<int,int>
#define clr(a,b) memset((a),b,sizeof(a))
#define rep(i,a,b) for(int i = a;i < b;i ++)
#define pb push_back
#define MP make_pair
#define LL long long
#define INT(t) int t; scanf("%d",&t)
#define LLI(t) LL t; scanf("%I64d",&t)
using namespace std;
const int maxn = 2e5 + 100;
const int inf = 0x3f3f3f3f;
vector<int> v[maxn];
struct xx{
int v,nex,w;
xx(){}
xx(int v,int nex,int w):
v(v),nex(nex),w(w){}
}edge[maxn * 5];
int d[maxn];
int head[maxn];
int cnt;
set<int> se;
void init(){
for(int i = 0;i < maxn;i ++) head[i] = -1;
for(int i = 0;i < maxn;i ++) v[i].clear();
cnt = 0;
se.clear();
}
void dij(int x){
clr(d,inf);
d[x] = 0;
priority_queue<pair<int,int> >Q;
Q.push(MP(-d[x],x));
while(!Q.empty()){
int now = Q.top().second;
Q.pop();
for(int i = head[now]; ~i;i = edge[i].nex){
int v = edge[i].v;
int dis = edge[i].w;
if(d[v] > d[now] + dis){
d[v] = d[now] + dis;
Q.push(MP(-d[v],v));
}
}
}
}
int main()
{
int t; scanf("%d",&t);
int cas = 1;
while(t --){
init();
int n,m,c; scanf("%d%d%d",&n,&m,&c);
for(int i = 1;i <= n;i ++){
int a; scanf("%d",&a);
v[a].pb(i);
se.insert(a);
}
set<int>::iterator it;
it = se.begin();
int last = *it;
for(int i = 0;i < v[last].size();i ++){
edge[cnt] = xx(v[last][i],head[n + last],0);
head[n + last] = cnt ++;
}
for(++ it;it != se.end();++ it){
int tmp = *it;
for(int i = 0;i < v[tmp].size();i ++){
edge[cnt] = xx(v[tmp][i],head[n + tmp],0);
head[n + tmp] = cnt ++;
}
if(tmp - last != 1){
last = tmp;
continue;
}
for(int i = 0;i < v[last].size();i ++){
edge[cnt] = xx(n + tmp,head[v[last][i]],c);
head[v[last][i]] = cnt ++;
}
for(int i = 0;i < v[tmp].size();i ++){
edge[cnt] = xx(n + last,head[v[tmp][i]],c);
head[v[tmp][i]] = cnt ++;
}
last = tmp;
}
for(int i = 0;i < m;i ++){
int a,b,c; scanf("%d%d%d",&a,&b,&c);
edge[cnt] = xx(b,head[a],c);
head[a] = cnt ++;
edge[cnt] = xx(a,head[b],c);
head[b] = cnt ++;
}
dij(1);
printf("Case #%d: ",cas ++);
if(d[n] == inf) printf("-1\n");
else printf("%d\n",d[n]);
}
return 0;
}