A. Copil Copac Draws Trees
https://codeforces.com/contest/1830/problem/A
题意:给定一棵树,初始时只有节点1。再给定n - 1条边,不断的扫描n - 1条边,如果边{u, v}已经在树中,则将边加入到树中,问建完树需要扫描多少次边?
思路:动态规划,从节点1做dfs。然后考虑当前的边{u, v}。假如{u, v}在输入序列中出现的顺序,比{p, u}靠后,那么dp[v] = inputIndex[{u, v}]; 否则,此时{p, u}的扫描次数已经计算出来,{u, v}的inputIndex在{p, u}的activeInex前面,那么dp[u] = dp[v] + 1,这种逻辑保证在考虑节点v前,dp[u]的数值总是有效的,最后去dp里取最大值即可。
总结:没有更好的理解题解,主要是那些变量太傻逼了,一会index[], 一会id[],不如改成inputIndex和activeIndex更好理解一点。
inline void solve() {
int n;
cin >> n;
vector<int> dp(n + 1);
vector<int> activeIndex(n + 1);
vector<vector<int>> al(n + 1);
map<pair<int, int>, int> index;
for (int i = 0; i < n - 1; ++i) {
int u, v;
cin >> u >> v;
al[u].push_back(v);
al[v].push_back(u);
index[{u, v}] = index[{v, u}] = i;
}
auto dfs = [&](auto&& self, int u, int p) ->void{
for (const auto& v : al[u]) {
if (v == p) {
continue;
}
dp[v] = dp[u] + (index[{u, v}] < activeIndex[u]);
activeIndex[v] = index[{u, v}];
self(self, v, u);
}
};
dp[1] = 1;
dfs(dfs, 1, 0);
cout << *max_element(dp.begin() + 1, dp.end()) << '\n';
}

浙公网安备 33010602011771号