Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Select Edges Editorial #5045

Merged
merged 3 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions content/4_Gold/DP_Trees.problems.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,7 @@
"isStarred": false,
"tags": ["Tree", "DP"],
"solutionMetadata": {
"kind": "autogen-label-from-site",
"site": "AC"
"kind": "internal"
}
},
{
Expand Down
92 changes: 92 additions & 0 deletions solutions/gold/ac-SelectEdges.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
---
id: ac-SelectEdges
source: AC
title: Select Edges
author: Justin Ji
---

## Explanation

To solve this problem, we write a tree DP. Consider that the only factor we
need to differentiate nodes on is whether or not we can connect a given node
to its parent. Thus, our DP state is the following:

- $\texttt{dp}[u][0]$ is the best result in the subtree of $u$ if we can connect $u$ to its parent
- $\texttt{dp}[u][1]$ is the best result in the subtree of $u$ if we can't connect $u$ to its parent

For a given node $u$, the "gain" we get from adding this node in is:

$$
(w + \texttt{dp}[u][0]) - \texttt{dp}[u][1]
$$

Thus, we want to use our $d[u]$ allowed edges on the nodes that have the most
benefit when adding an edge to them. Note that we handle the cases for
$\texttt{dp}[u][0])$ and $\texttt{dp}[u][1]$ pretty similarly.

## Implementation

**Time Complexity:** $\mathcal{O}(N\log{N})$

<LanguageSection>
<CPPSection>

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

using ll = long long;

int main() {
int n;
cin >> n;

vector<int> d(n);
for (int &i : d) { cin >> i; }

vector<vector<array<int, 2>>> adj(n);
for (int i = 0; i < n - 1; i++) {
int u, v, w;
cin >> u >> v >> w;
u--, v--;
adj[u].push_back({v, w});
adj[v].push_back({u, w});
}

// DP state is for the relation with its parent node
// {can connect, can't connect}
vector<array<ll, 2>> dp(n);
const auto dfs = [&](int u, int p, auto self) -> void {
TheGamingMousse marked this conversation as resolved.
Show resolved Hide resolved
auto &[can_con, no_con] = dp[u];
vector<ll> diffs; // diff between using edge and not using edge

for (const auto &[v, w] : adj[u]) {
if (v == p) { continue; }
self(v, u, self);
can_con += dp[v][1];
no_con += dp[v][1];
if (d[v] > 0) { diffs.push_back(w + dp[v][0] - dp[v][1]); }
}

int leftover = d[u];

sort(begin(diffs), end(diffs), greater());
for (const ll &val : diffs) {
if (leftover == 0 || val < 0) { break; }
if (leftover > 1) {
can_con += val;
no_con += val;
} else {
no_con += val;
}
leftover--;
}
};
dfs(0, -1, dfs);

cout << dp[0][1] << endl;
}
```

</CPPSection>
</LanguageSection>
Loading