标签:
题意:有 n 个点,每个点有它所在的层数,最多有 n 层,相邻两层之间的点可以互相到达,消耗 c (但同一层并不能直接到达),然后还有一些额外的路径,可以在两点间互相到达,并且消耗一定费用。问 1 点到 n 点的最小花费
将每一层拆成两个点,分别为进入层和出发层,然后相邻层的出发层可以指向进入层,花费 c,每个点可以到达其出发层,而进入层可以到达该点,花费 0 ,最后建立其余双向边,最短路
1 #include<stdio.h>
2 #include<string.h>
3 #include<vector>
4 #include<algorithm>
5 #include<queue>
6 using namespace std;
7 typedef pair<int,int> pii;
8
9 struct cmp{
10 bool operator()(pii a,pii b){
11 return a.first>b.first;
12 }
13 };
14
15 int head[300005],point[1000005],val[1000005],nxt[1000005],size;
16 int n,dist[300005];
17
18 void add(int a,int b,int v){
19 point[size]=b;
20 val[size]=v;
21 nxt[size]=head[a];
22 head[a]=size++;
23 }
24
25 void dij(){
26 int i;
27 memset(dist,-1,sizeof(dist));
28 dist[1]=0;
29 priority_queue<pii,vector<pii>,cmp>q;
30 q.push(make_pair(dist[1],1));
31 while(!q.empty()){
32 pii u=q.top();
33 q.pop();
34 if(u.first>dist[u.second])continue;
35 for(i=head[u.second];~i;i=nxt[i]){
36 int j=point[i],v=u.first+val[i];
37 if(dist[j]==-1||dist[j]>v){
38 dist[j]=v;
39 q.push(make_pair(dist[j],j));
40 }
41 }
42 }
43 printf("%d\n",dist[n]);
44 }
45
46 int main(){
47 int t;
48 while(scanf("%d",&t)!=EOF){
49 for(int q=1;q<=t;q++){
50 printf("Case #%d: ",q);
51 memset(head,-1,sizeof(head));
52 size=0;
53 int m,c;
54 scanf("%d%d%d",&n,&m,&c);
55 int i,j;
56 for(i=1;i<=n;i++){
57 int l;
58 scanf("%d",&l);
59 add(i,l+n,0);
60 add(l+n+n,i,0);
61 }
62 for(i=1;i<n;i++){
63 add(i+n,i+n+n+1,c);
64 add(i+n+1,i+n+n,c);
65 }
66 for(i=1;i<=m;i++){
67 int a,b,v;
68 scanf("%d%d%d",&a,&b,&v);
69 add(a,b,v);
70 add(b,a,v);
71 }
72 dij();
73 }
74 }
75 return 0;
76 }
标签:
原文地址:http://www.cnblogs.com/cenariusxz/p/4787506.html