0%

牛客小白月赛102-D-最短?路径

题目大意

给定一个图,边有权值。在节点上每经过 k 条边必须休息一次(或者说每走 k 步必须停顿)。求从起点到终点的最短时间(或路径权值和),考虑休息带来的限制/代价。

AC代码

参考了官方题解思路,就是在分层图上跑最短路

image

相比于TLE代码,只加了个这个优化

while(!q.empty() && dist[n+1]==INF)

如果dist[n+1]已经确定,那就不用再跑了。

然后代码实现上有比较多的细节,主要是在初始化方面,比如说vis[i][0]也要清理什么的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// https://ac.nowcoder.com/acm/contest/91355/D
#include <iostream>
#include <set>
#include <vector>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
const ll N=2e5+10,INF=1e18+7;
ll T,n,m,k,a[N],u,v,dist[N];
vector<ll> e[N];
bool vis[N][11];
struct edge {
ll node,dis,nrest; // nrest 为多久没休息了
};
struct cmp {
bool operator()(edge a,edge b) {
if(a.dis!=b.dis)
return a.dis>b.dis;
return a.node<b.node;
}
};
priority_queue<edge,vector<edge>,cmp > q;
edge make_edge(ll node,ll dis,ll nrest) {
edge temp;
temp.node=node;temp.dis=dis;temp.nrest=nrest;
return temp;
}
void dijkstra(int t) {
q.push(make_edge(1,0,0));
while(!q.empty() && dist[n+1]==INF) {
ll node=q.top().node,dis=q.top().dis,nrest=q.top().nrest;
q.pop();
if(vis[node][nrest]) // 之前访问过,弹出
continue;
vis[node][nrest]=true;
dist[node]=min(dis,dist[node]);
for(int i=0;i<e[node].size();i++) {
if(nrest>=k)
q.push(make_edge(e[node][i],dis+a[node],0));
else {
q.push(make_edge(e[node][i],dis+a[node],0));
q.push(make_edge(e[node][i],dis+1,nrest+1));
}
}
}
}
void clear() {
priority_queue<edge,vector<edge>,cmp > empty;
swap(empty,q);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>T;
for(int _=1;_<=T;_++) {
cin>>n>>m>>k;
clear();
for(int i=1;i<=n+1;i++)
e[i].clear();
for(int i=1;i<=n;i++) {
cin>>a[i];
}
fill(&dist[1],&dist[n+2],INF);
for(int i=1;i<=n+1;i++)
for(int j=0;j<=k;j++)
vis[i][j]=false;
for(int i=1;i<=m;i++) {
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
e[n].push_back(n+1);
e[n+1].push_back(n);
dijkstra(_);
cout<<dist[n+1]<<endl;
}
return 0;
}
// TLE https://ac.nowcoder.com/acm/contest/view-submission?submissionId=72128029
// AC https://ac.nowcoder.com/acm/contest/view-submission?submissionId=72128343

心路历程(WA,TLE,MLE……)

过了40% TLE https://ac.nowcoder.com/acm/contest/view-submission?submissionId=72128029

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// https://ac.nowcoder.com/acm/contest/91355/D
#include <iostream>
#include <set>
#include <vector>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long ll;
const ll N=2e5+10,INF=1e18+7;
ll T,n,m,k,a[N],u,v,dist[N];
vector<ll> e[N];
bool vis[N][11];
struct edge {
ll node,dis,nrest; // nrest 为多久没休息了
};
struct cmp {
bool operator()(edge a,edge b) {
if(a.dis!=b.dis)
return a.dis>b.dis;
return a.node<b.node;
}
};
priority_queue<edge,vector<edge>,cmp > q;
edge make_edge(ll node,ll dis,ll nrest) {
edge temp;
temp.node=node;temp.dis=dis;temp.nrest=nrest;
return temp;
}
void dijkstra(int t) {
q.push(make_edge(1,0,0));
while(!q.empty()) {
ll node=q.top().node,dis=q.top().dis,nrest=q.top().nrest;
q.pop();
if(vis[node][nrest]) // 之前访问过,弹出
continue;
vis[node][nrest]=true;
dist[node]=min(dis,dist[node]);
for(int i=0;i<e[node].size();i++) {
if(nrest>=k)
q.push(make_edge(e[node][i],dis+a[node],0));
else {
q.push(make_edge(e[node][i],dis+a[node],0));
q.push(make_edge(e[node][i],dis+1,nrest+1));
}
}
}
}
void clear() {
priority_queue<edge,vector<edge>,cmp > empty;
swap(empty,q);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>T;
for(int _=1;_<=T;_++) {
cin>>n>>m>>k;
clear();
for(int i=1;i<=n+1;i++)
e[i].clear();
for(int i=1;i<=n;i++) {
cin>>a[i];
}
fill(&dist[1],&dist[n+2],INF);
for(int i=1;i<=n+1;i++)
for(int j=0;j<=k;j++)
vis[i][j]=false;
for(int i=1;i<=m;i++) {
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
e[n].push_back(n+1);
e[n+1].push_back(n);
dijkstra(_);
cout<<dist[n+1]<<endl;
}
return 0;
}
// TLE https://ac.nowcoder.com/acm/contest/view-submission?submissionId=72128029