Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
题目大意:给n个点,m条无向边,边权w,为走这条路的代价。每个点属于某一层,从某层到隔壁层代价都是固定的c,求1到n最短路。
因为每个点可以借助层的属性,到达其他点就有了其他的路径。所以有必要把每层也抽象出额外的点。因为每层的点也是不连通的,就是说如果点i和点j在同一层,并不代表他们之间距离就是0。所以对于层节点,还需要拆点。将每层的点拆成i+n和i + n + n 2个点。i+n表示进入第i层,i+n+n表示从第i层出去。建图的时候如果某点j属于第i层,那么
j—>i + n连一条权为0的边,i + n + n —>j连一条权为0的边。对于层与层之间的关系,因为层抽象出来的点只是一个中间媒介点,所以对于进入第i层的边,只可能通过i+n这个点直接从隔壁层出去,于是i+n—>i +1 + n + n连边,边权c,i + n +1 —>i + n + n连边,边权c。注意虽然第i层被抽象出了i+n和I+ n + n2个点,但他们之间不能连边,因为同一层的点距离不为0,连边了就失去了拆点的意义。
#include <iostream> #include <stdio.h> #include <string> #include <stdlib.h> #include <string.h> #include <algorithm> #include <math.h> #include <fstream> #include <vector> #include <queue> #define Min(a,b) ((a)<(b)?(a):(b)) #pragma comment(linker, "/STACK:16777216") using namespace std ; typedef __int64 LL ; const int size=300008 ; const int inf=2000000000 ; struct Edge{ int v ; int w ; int next ; }; Edge edge[size*3] ; int vec[size] ; int dist[size] ; int id ; int N , M , C; void init(){ id=0 ; fill(vec,vec+1+3*N,-1) ; fill(dist,dist+1+3*N,inf) ; } inline void add_edge(int u ,int v ,int w){ edge[id].v=v ; edge[id].w=w ; edge[id].next=vec[u] ; vec[u]=id++ ; } struct Node{ int id ; int dis ; Node(){} ; Node(int i ,int d):id(i),dis(d){} ; friend bool operator <(const Node A ,const Node B){ return A.dis>B.dis ; } }; int bfs(){ priority_queue<Node>que ; que.push(Node(1,0)) ; dist[1]=0 ; while(!que.empty()){ Node now=que.top(); que.pop() ; if(now.id==N) return now.dis ; int u=now.id ; for(int e=vec[u];e!=-1;e=edge[e].next){ int v=edge[e].v ; int w=edge[e].w ; if(now.dis+w<dist[v]){ dist[v]=now.dis+w ; que.push(Node(v,dist[v])) ; } } } return -1 ; } int getint(){ char c=getchar(); int t=0; while(c<'0'||c>'9'){ c=getchar(); } while(c>='0'&&c<='9'){ t=t*10+c-'0'; c=getchar(); } return t; } int gao(){ int x ,u ,v ,w; N=getint() ; M=getint() ; C=getint() ; init() ; for(int i=1;i<=N;i++){ u=getint() ; add_edge(i,u+N,0) ; add_edge(u+N+N,i,0) ; } for(int i=1;i<N;i++){ add_edge(i+N,i+1+N+N,C) ; add_edge(i+1+N,i+N+N,C) ; } while(M--){ u=getint() ; v=getint() ; w=getint() ; add_edge(u,v,w) ; add_edge(v,u,w) ; } if(N==0) return -1 ; if(N==1) return 0 ; return bfs() ; } int main(){ int T ,k=1; cin>>T ; while(T--){ printf("Case #%d: %d\n",k++,gao()) ; } return 0 ; }