🐷
ABC341F
問題
解法
駒を一つ固定して考える.
無向グラフと書かれているが,コストが真に小さい vertex に駒を(必要なら増やした上で)移動するので,
有限回で終わるかつ有向グラフとみなしてよい.
式で表せば
と書ける.
つまり,
- コストを
,W_{u} - 価値を
dp_{u}
とするナップザック問題を解けば求まる.
このとき,頂点全体をソートしておけば十分.
コード
main.cpp
int main() {
ll n,m;
cin >> n >> m;
vvll to(n);
rep(i,m){
ll a,b; cin >> a >> b;
--a, --b;
to[a].emplace_back(b);
to[b].emplace_back(a);
}
vll w(n), a(n);
cinv(w); cinv(a);
vll vs(n); rep(i,n) vs[i] = i;
sort(all(vs), [=](ll i, ll j){ return w[i] < w[j]; });
vll dp(n);
for(auto v: vs){ // rem: for の内部で dp[u] (u < v in vs) を用いている事を確認
// max_val を Knapsack problem を解いて求める.
// cost(u) = w[u],
// value(u) = dp[u]
vll knapsack_cost_to_val(w[v]);
for(auto u: to[v]) if(w[u] < w[v]){
drep(cost, w[v]){ // w[v] 未満しか使わない
if(cost - w[u] < 0) break;
chmax(knapsack_cost_to_val[cost], knapsack_cost_to_val[cost - w[u]] + dp[u]);
}
}
ll max_val = 0;
rep(cost, w[v]) chmax(max_val, knapsack_cost_to_val[cost]);
chmax(dp[v], max_val + 1);
}
ll ans = 0;
rep(v,n) ans += a[v] * dp[v];
cout << ans << endl;
return 0;
}
Discussion