题目大意
给了若干个点,每个点分属于一个层,同层之间的点不能够直接到达,但是相邻层的可以到达,代价是c,现在在这个基础之上,给了若干条无向边,现在要求结点1到结点n的路径的最小代价。
此题的难点在于建图
现在我们将层这个概念变成实际意义上的结点,层这个虚拟概念正式成为两个结点,第r层,对应的结点编号是,n + u * 2 - 1 ,和, n + u * 2 。i 结点对应的层数是r,那么 令 i 到 n + u * 2 - 1 有一条有向边, 令 n + u * 2 到 i 也有一条有向边 。两条有向边的代价均为 0 。
为什么将代价设为0 ?
层是结点的基础属性,由结点映射到层,不需要任何代价。
接下来我们给相邻层数建边。
add_ead( n + 2 * i - 1 , n + 2 * (i + 1) , c );
add_ead( n + 2 * (i + 1) - 1 , n + 2 * i , c );
为什么,点和层间,进入的层点,成为了,层和层间,出发的点 ?
为了形成一个环。
这样,由点,到层,再到层,再到点,这条路径,
在原图中对应的路径,才能吻合,
也就是说,我们要保证重新建立的图和原来的图要相互吻合。
继续建图,建立结点和结点之间的无向图。
接着利用dijkstra。
AC code
#include<iostream>
#include<queue>
#include<cstring>
#include<string>
#include<sstream>
#include<map>
#include<vector>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<stack>
#include<ctime>
using namespace std;
#define rep(i,aa,bb) for(register int i=aa;i<=bb;i++)
#define rrep(i,aa,bb) for(register int i=aa;i>=bb;i--)
#define mset(var,val) memset(var,val,sizeof(var))
#define LL long long
#define eps 0.000001
#define inf 0x7f7f7f7f
#define llinf 1e18
#define exp 0.000001
#define pai 3.141592654
#define random(x) rand()%(x)
#define lowbit(x) x&(-x)
inline int read()
{
int x=0,y=1;char a=getchar();while ( a>'9' || a<'0'){if ( a=='-')y=-1;a=getchar();}
while ( a>='0' && a<='9' ){ x=(x<<3)+(x<<1)+a-'0'; a=getchar();}return x*y;
}
#define N 500005
struct Ead{
int u,v,w,nx;
}e[N];int hea[N],tot;bool islay[N];int n,m,c,dis[N];
void init(){
mset(hea,0);
mset(islay,0);
mset(dis,0x7f);
tot = 0;
}
void add_ead(int u,int v,int w){
++tot;
e[tot].u = u; e[tot].v = v; e[tot].w = w; e[tot].nx = hea[u]; hea[u] = tot;
}
struct Node {
int v,w;
Node() {}
Node ( int a_ ,int b_ ) { v = a_ ; w = b_ ; }
bool operator < ( const Node& aaa ) const {
return w > aaa.w;
}
};
void dijkstra( int st ){
dis[ st ] = 0 ;
priority_queue< Node >q ;
while ( !q.empty() ) q.pop() ;
Node xxx ; xxx.v = 1; xxx.w = 0;
q.push( xxx );
while ( !q.empty() ){
Node now = q.top(); q.pop();
if ( dis[ now.v ] != now.w ) continue;
for (int i = hea[ now.v ] ; i ; i = e[i].nx ){
if ( dis[ e[i].v ] > dis[ e[i].u ] + e[i].w ){
// printf("%d %d %d\n", e[i].u, e[i].v ,e[i].w);
dis[ e[i].v ] = dis[ e[i].u ] + e[i].w;
xxx.v = e[i].v ; xxx.w = dis[ e[i].v ];
q.push( xxx );
}
}
}
}
int main()
{
// freopen("1.txt","r",stdin);
// srand((int)time(0));
// std::ios::sync_with_stdio(false);
int T = read();
rep(aai,1,T){
init();
n = read(); m = read(); c = read();
rep(i,1,n){
int u; u = read();
add_ead( i , n + u * 2 - 1 , 0 );
add_ead( n + u * 2 , i , 0 );
islay[ u ] = true;
}
rep(i,1,n){
if ( islay[i] && islay[ i + 1 ] ){
add_ead( n + 2 * i - 1 , n + 2 * (i + 1) , c );
add_ead( n + 2 * (i + 1) - 1 , n + 2 * i , c );
}
}
rep(i,1,m){
int u,v,w;
u = read(); v = read(); w = read();
add_ead(u,v,w);
add_ead(v,u,w);
}
dijkstra(1);
if ( dis[ n ] == inf || n == 0 )
printf("Case #%d: -1\n",aai);
else
printf("Case #%d: %d\n",aai,dis[n]);
}
return 0;
}