题意:
有n个点,n层(不一定每层只有一个点,可能有的层没有点),第i个点属于第a[i]层,相邻两层之间的点可以互相到达且距离为c,此外还有m条节点与节点之间的无向边,求最短路。
思路:
每一层建立一个超级源点,这个源点到该层的所有点的距离为0,注意此处是单向边,然后相邻层的超级源点距离为c(无向边),然后再正常添加m条边(无向边)即可,即一共有3种边,该图中有不超过2n个点,分别是n个点和<=n个超级源点。
注意题目中n, m <= 1e5, 实际上数组开3e5一直wa,6e5ac了,还没懂为啥
// Decline is inevitable, romance will last forever.
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string>
#include <cstdio>
using namespace std;
#define mst(a, x) memset(a, x, sizeof(a))
#define INF 0x3f3f3f3f
#define P 998244353
//#define int long long
const int maxn = 6e5 + 10;
const int maxm = 6e5 + 10;
int n, m, c;
int a[maxn];
struct Edge {
int to, dis, next;
}edge[maxm];
int head[maxn], dis[maxn], cnt;
bool vis[maxn], vis2[maxn];
struct node {
int dis;
int pos;
node(int _dis = 0, int _pos = 0) : dis(_dis), pos(_pos) {}
bool operator <(const node &x) const {
return dis > x.dis;
}
};
void add_edge(int u, int v, int w) {
cnt++;
edge[cnt].to = v;
edge[cnt].dis = w;
edge[cnt].next = head[u];
head[u] = cnt;
}
priority_queue<node> q;
void dijkstra(int s) {
mst(vis, 0);
mst(dis, 0x3f);
dis[s] = 0;
q.push(node(0, s));
while(!q.empty()) {
node tmp = q.top();
q.pop();
int x = tmp.pos;
if(vis[x]) continue;
vis[x] = true;
for(int i = head[x]; i; i = edge[i].next) {
int y = edge[i].to;
if(dis[y] > dis[x] + edge[i].dis)
dis[y] = dis[x] + edge[i].dis,
q.push(node(dis[y], y));
}
}
}
int t = 0;
void solve() {
mst(vis2, 0);
mst(head, 0);
mst(a, 0);
cnt = 0;
scanf("%d%d%d", &n, &m, &c);
// cin >> n >> m >> c;
int mi = INF;
int mx = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
// cin >> a[i];
a[i] += n;
vis2[a[i]] = true;
mx = max(mx, a[i]);
mi = min(mi, a[i]);
add_edge(a[i], i, 0); //注意此处不能加双向边
}
for(int i = 1; i <= n; i++)
{
/* if(vis2[i] && vis2[i+1])
{
add_edge(i, i+1, c);
add_edge(i+1, i, c);
} */
if(vis2[a[i] + 1]) add_edge(i, a[i] + 1, c);
if(vis2[a[i] - 1]) add_edge(i, a[i] - 1, c);
}
for(int i = 1; i <= m; i++) {
int u, v, w;
// cin >> u >> v >> w;
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w);
add_edge(v, u, w);
}
dijkstra(1);
t++;
if(dis[n] != INF)
printf("Case #%d: %d\n", t, dis[n]);
else printf("Case #%d: -1\n", t);
}
signed main() {
int T; scanf("%d", &T); while(T--)
// int T; cin >> T; while(T--)
solve();
return 0;
}