Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_图论


Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_算法_02


题意

  • 给一个图,Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_算法_03 个点 Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_图论_04 条边,Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_数据_05 次询问,求从 Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_动态规划_06Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_动态规划_07 的走过条数不超过 Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_最短路_08
  • 数据范围:Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_最短路_09 点,Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_最短路_10 边,Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_数据_11 次询问,时间要求 Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_图论_12

题解

  • 定义Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_图论_13为从Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_动态规划_14Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_算法_15,恰好走Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_最短路_16
  • 由于我们要满足路径边权递增,所以会想到给所有边按照边权排个序。然后我们依次将边加入图中,这样就可以保证路径边权是递增的。
  • 我们会注意到,由于任意两个点间的路径不能存在环(路径边权递增),所以任意两个点之间的距离至多为Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_图论_17,这样我们就把Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_最短路_18减小为Problem C. Increasing Shortest Path【贪心 & 最短路->DP】_图论_17

AC-Code

#include <bits/stdc++.h>
using namespace std;

const int maxm = 3e3 + 5;
const int maxn = 150 + 3;
const int mod = 1e9 + 7;

struct Edge {
int x, y, w;
bool operator < (const Edge &t) const {
return w < t.w;
}
}edge[maxm];

int dp[maxn][maxn][maxn];

void update(int& a, int b) {
if (a == -1 || b < a) a = b; // 如果无法到达,或者b更优,更新
}

int main() {
int T; cin >> T;
while (T--) {
int N, M, Q; cin >> N >> M >> Q;
memset(dp, -1, sizeof dp);
for (int i = 0; i <= N; ++i) dp[i][i][0] = 0;
for (int i = 1; i <= M; ++i)
cin >> edge[i].x >> edge[i].y >> edge[i].w;
sort(edge + 1, edge + 1 + M);
for (int i = 1; i <= M; ++i) // 升序枚举所有边
for (int start = 1; start <= N; ++start) // 枚举起点
for (int step = 1; step < N; ++step) // 枚举步数
if (dp[start][edge[i].x][step - 1] != -1) // 如果可以从start到达这条边的起点
update(dp[start][edge[i].y][step], dp[start][edge[i].x][step - 1] + edge[i].w); // 尝试走这条边到达edge[i].y
for (int i = 0; i < Q; ++i) {
int x, y, c; cin >> x >> y >> c;
if (c >= N) c = N - 1; //
int ans = -1;
for (int j = 0; j <= c; ++j)
if (dp[x][y][j] != -1) update(ans, dp[x][y][j]);
cout << ans << endl;
}
}
return 0;
}