feat: 添加P3077题解实现最大权值路径算法

This commit is contained in:
Zengtudor 2025-11-19 23:46:05 +08:00
parent 8b39f98492
commit 0f4b3eef8f

70
src/11/19/P3077.cpp Normal file
View File

@ -0,0 +1,70 @@
#include <algorithm>
#include <iostream>
#include <vector>
using ll = int64_t;
ll n, m, r, ans;
std::vector<ll> a, b;
std::vector<std::vector<ll>> ea; // 只保留左到右的邻接表即可
std::vector<ll> dpa, dpb; // 不需要二维数组,一维即可
int main() {
// 优化输入输出
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin >> n >> m >> r;
// 调整大小
a.resize(n + 1);
b.resize(m + 1);
ea.resize(n + 1);
dpa.resize(n + 1);
dpb.resize(m + 1);
// 读入左岸权值并初始化 DP 和 ans
for (ll i = 1; i <= n; i++) {
std::cin >> a[i];
dpa[i] = a[i]; // 路径可以只包含这一个点
ans = std::max(ans, a[i]);
}
// 读入右岸权值并初始化 DP 和 ans
for (ll i = 1; i <= m; i++) {
std::cin >> b[i];
dpb[i] = b[i]; // 路径可以只包含这一个点
ans = std::max(ans, b[i]);
}
// 读入边,只存单向即可(左->右),后续通过排序处理顺序
for (ll i = 1; i <= r; i++) {
ll u, v;
std::cin >> u >> v;
ea[u].push_back(v);
}
// 核心逻辑:按照左岸点 u 从小到大,右岸点 v 从小到大的顺序处理每一条边
// 这等同于正解中的 sort(e+1, e+r+1)
for (ll i = 1; i <= n; i++) {
// 对当前左岸点 i 连接的所有右岸点进行排序
std::sort(ea[i].begin(), ea[i].end());
for (ll j : ea[i]) {
// 暂存数值,避免更新顺序影响(同正解中的 t1, t2
// 从右岸 j 走到 左岸 i
ll val_to_left = dpb[j] + a[i];
// 从左岸 i 走到 右岸 j
ll val_to_right = dpa[i] + b[j];
// 更新 DP 表
dpa[i] = std::max(dpa[i], val_to_left);
dpb[j] = std::max(dpb[j], val_to_right);
// 更新全局答案
ans = std::max({ans, dpa[i], dpb[j]});
}
}
std::cout << ans << "\n";
}