首先发出题目链接:
链接:https://ac.nowcoder.com/acm/contest/884/J
来源:牛客网
涉及:分层图,dp
点击这里回到2019牛客暑期多校训练营解题—目录贴
题目如下:
代码如下
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
typedef long long ll;
typedef pair<ll, int> Edge;
const int maxn = 1e3+5;
const int inf = 1e7;
vector<Edge> vec[maxn*maxn];
ll mp[maxn][maxn];
int n, m, s, t, k;
ll d[maxn*maxn];
priority_queue<Edge, vector<Edge>, greater<Edge> > que;
int main(){
scanf("%d%d%d%d%d", &n, &m, &s, &t, &k);
memset(d, 0x7f, sizeof(d));
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
mp[i][j] = inf;
}
}
int invm = m;
for(int i = 1; i <= m; i++){
int a, b;
ll l;
scanf("%d%d%lld", &a, &b, &l);
if(a == b) invm--;
else if(mp[a][b] != inf) invm--;
mp[a][b] = mp[b][a] = min(mp[b][a], l);
}
m = invm;
for(int i = 1; i <= n; i++){
for(int j = i+1; j <= n; j++){
if(mp[i][j] != inf){
for(int l = 0; l <= m; l++){
vec[i+l*n].push_back(Edge(mp[i][j], j+l*n));
vec[j+l*n].push_back(Edge(mp[i][j], i+l*n));
if(l){
vec[i+(l-1)*n].push_back(Edge(0, j+l*n));
vec[j+(l-1)*n].push_back(Edge(0, i+l*n));
}
}
}
}
}
k = min(k, m);
t = t + k * n;
d[s] = 0;
que.push(Edge(0, s));
while(que.size()){
Edge edge = que.top();
que.pop();
int u = edge.second;
ll w = edge.first;
if(d[u] < w) continue;
for(int i = 0; i < vec[u].size(); i++){
int v = vec[u][i].second;
if(v > (k+1)*n) continue;
if(d[v] > d[u] + vec[u][i].first){
d[v] = d[u] + vec[u][i].first;
que.push(Edge(d[v], v));
}
}
}
printf("%lld", d[t]);
return 0;
}