题意:

n层图,每个点放在一层,然后给了n个点,相邻的两层距离是固定的c,有额外m条边,然后求1到n的最短路径,如果没有则输出-1

 

题解:

这道题原来我想着还用1到n表示点,层用n+1到2*n表示,但是这样是不行的,因为这样建图的话就相当于同层之间的距离为0.但是事实证明不是这样的

我按照上面建图就Wa了


HDU - 4725 最短路_出点HDU - 4725 最短路_ios_02


1 #include<stdio.h>
2 #include<string.h>
3 #include<iostream>
4 #include<algorithm>
5 #include<queue>
6 #include<vector>
7 using namespace std;
8 const int INF=0x3f3f3f3f;
9 const int maxn=3e5+5;
10 #define MAX 0xffffff
11 struct shudui1
12 {
13 int start,value;
14 bool operator < (const shudui1 q)const
15 {
16 return value>q.value;
17 }
18 } str1;
19 struct shudui2
20 {
21 int start,value;
22 } str2;
23 int v[maxn];
24 priority_queue<shudui1>r;
25 vector <shudui2>w[maxn];
26 void JK(int s)
27 {
28 memset(v,INF,sizeof(v));
29 v[s]=0;
30 str1.start=s;
31 str1.value=0;
32 r.push(str1);
33 while(!r.empty())
34 {
35 int x,y;
36 str1=r.top();
37 r.pop();
38 x=str1.start;
39 y=str1.value;
40 if(v[x]<y) continue;
41 int len=w[x].size();
42 for(int i=0; i<len; ++i)
43 {
44 str2=w[x][i];
45 if((v[x]+str2.value<v[str2.start]))
46 {
47 v[str2.start]=v[x]+str2.value;
48 str1.start=str2.start;
49 str1.value=v[str2.start];
50 r.push(str1);
51 }
52 }
53 }
54 }
55 int main()
56 {
57 int t,p=0;
58 scanf("%d",&t);
59 while(t--)
60 {
61 int n,m,k;
62 scanf("%d%d%d",&n,&m,&k);
63 for(int i=1;i<=2*n;++i)
64 w[i].clear();
65 for(int i=1;i<=n;++i)
66 {
67 int x;
68 scanf("%d",&x);
69 str2.start=n+x;
70 str2.value=0;
71 w[i].push_back(str2);
72 str2.start=i;
73 w[n+x].push_back(str2);
74 }
75 for(int i=2;i<=n;++i)
76 {
77 str2.start=n+i;
78 str2.value=k;
79 w[n+i-1].push_back(str2);
80 str2.start=n+i-1;
81 w[n+i].push_back(str2);
82 }
83 for(int i=1;i<=m;++i)
84 {
85 int x,y,z;
86 scanf("%d%d%d",&x,&y,&z);
87 str2.start=y;
88 str2.value=z;
89 w[x].push_back(str2);
90 str2.start=x;
91 w[y].push_back(str2);
92 }
93 JK(1);
94 if(v[n]!=INF)
95 printf("Case #%d: %d\n",++p,v[n]);
96 else printf("Case #%d: -1\n",++p);
97 }
98 return 0;
99 }

View Code

 

 

那就只好把每一层分成两个点,一个当作入点,一个当作出点。

第i层,入边到N+2*i-1, 出边从N+2*i 出来。(1<= i <= N)

N + 2*i    到  N + 2*(i+1)-1 加边长度为C. 表示从第i层到第j层。

N + 2*(i+1) 到 N + 2*i - 1 加边长度为C,表示第i+1层到第j层。

 

建完图直接最短路就行了

AC代码:



1 #include<stdio.h>
2 #include<string.h>
3 #include<iostream>
4 #include<algorithm>
5 #include<queue>
6 #include<vector>
7 using namespace std;
8 const int INF=0x3f3f3f3f;
9 const int maxn=3e5+5;
10 #define MAX 0xffffff
11 struct shudui1
12 {
13 int start,value;
14 bool operator < (const shudui1 q)const
15 {
16 return value>q.value;
17 }
18 } str1;
19 struct shudui2
20 {
21 int start,value;
22 } str2;
23 int v[maxn];
24 priority_queue<shudui1>r;
25 vector <shudui2>w[maxn];
26 void JK(int s)
27 {
28 memset(v,INF,sizeof(v));
29 v[s]=0;
30 str1.start=s;
31 str1.value=0;
32 r.push(str1);
33 while(!r.empty())
34 {
35 int x,y;
36 str1=r.top();
37 r.pop();
38 x=str1.start;
39 y=str1.value;
40 if(v[x]<y) continue;
41 int len=w[x].size();
42 for(int i=0; i<len; ++i)
43 {
44 str2=w[x][i];
45 if((v[x]+str2.value<v[str2.start]))
46 {
47 v[str2.start]=v[x]+str2.value;
48 str1.start=str2.start;
49 str1.value=v[str2.start];
50 r.push(str1);
51 }
52 }
53 }
54 }
55 int main()
56 {
57 int t,p=0;
58 scanf("%d",&t);
59 while(t--)
60 {
61 int n,m,k;
62 scanf("%d%d%d",&n,&m,&k);
63 for(int i=1;i<=3*n;++i)
64 w[i].clear();
65 for(int i=1;i<=n;++i)
66 {
67 int x;
68 scanf("%d",&x);
69 str2.start=n+2*x-1;
70 str2.value=0;
71 w[i].push_back(str2);
72 str2.start=i;
73 w[n+2*x].push_back(str2);
74 }
75 for(int i=1;i<n;++i)
76 {
77 str2.start=n+2*(i+1);
78 str2.value=k;
79 w[n+2*i-1].push_back(str2);
80
81 str2.start=n+2*i;
82 w[n+2*(i+1)-1].push_back(str2);
83 }
84 for(int i=1;i<=m;++i)
85 {
86 int x,y,z;
87 scanf("%d%d%d",&x,&y,&z);
88 str2.start=y;
89 str2.value=z;
90 w[x].push_back(str2);
91 str2.start=x;
92 w[y].push_back(str2);
93 }
94 JK(1);
95 if(v[n]!=INF)
96 printf("Case #%d: %d\n",++p,v[n]);
97 else printf("Case #%d: -1\n",++p);
98 }
99 return 0;
100 }