Problem C. Increasing Shortest Path【贪心 & 最短路->DP】
原创
©著作权归作者所有:来自51CTO博客作者Nirvana柒的原创作品,请联系作者获取转载授权,否则将追究法律责任
题意
- 给一个图, 个点 条边, 次询问,求从 到 的走过条数不超过
- 数据范围: 点, 边, 次询问,时间要求
题解
- 定义为从到,恰好走
- 由于我们要满足路径边权递增,所以会想到给所有边按照边权排个序。然后我们依次将边加入图中,这样就可以保证路径边权是递增的。
- 我们会注意到,由于任意两个点间的路径不能存在环(路径边权递增),所以任意两个点之间的距离至多为,这样我们就把减小为
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;
}