This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
vector<vector<pair<unsigned, unsigned>>> g;
pair<int, unsigned> find_cycle(unsigned u, vector<unsigned> &c, vector<bool> &vis, unsigned p = -1)
{
if (vis[u])
return {1, u};
vis[u] = 1;
for (auto const &[v, w] : g[u])
if (v != p)
{
auto const [b, x] = find_cycle(v, c, vis, u);
if (b == 1)
{
c.push_back(u);
return {u == x ? 2 : 1, x};
}
if (b == 2)
return {2, x};
}
return {0, UINT_MAX};
}
// Returns (longest path inside subtree, longest path to root)
pair<int64_t, int64_t> longest_tree_path(unsigned u, unsigned p = -1)
{
pair<int64_t, int64_t> ans = {0, 0};
for (auto const &[v, w] : g[u])
{
if (v != p)
{
auto const [sl, rl] = longest_tree_path(v, u);
ans.first = max(ans.first, max(sl, ans.second + rl + w));
ans.second = max(ans.second, rl + w);
}
}
return ans;
}
int64_t longest_simple_path(unsigned u, vector<bool> &cvis)
{
vector<unsigned> c;
find_cycle(u, c, cvis);
if (c.empty())
return longest_tree_path(u).first;
size_t const m = c.size();
vector<int64_t> root_paths(c.size());
int64_t ans = 0;
vector<unsigned> pre_dis(c.size()), next_dis(c.size());
int64_t sum = 0;
for (size_t i = 0; i < m; i++)
{
auto it = lower_bound(g[c[i]].begin(), g[c[i]].end(), make_pair(c[(i + 1) % m], 0U));
assert(it != g[c[i]].end());
next_dis[i] = it->second;
sum += it->second;
g[c[i]].erase(it);
auto jt = lower_bound(g[c[i]].begin(), g[c[i]].end(), make_pair(c[(i - 1 + m) % m], 0U));
assert(jt != g[c[i]].end());
pre_dis[i] = jt->second;
g[c[i]].erase(jt);
}
for (size_t i = 0; i < m; i++)
{
auto const [sl, rl] = longest_tree_path(c[i]);
ans = max(ans, sl);
root_paths[i] = rl;
}
int64_t dp1 = 0, dp2 = 0, prefix_sum = 0;
for (size_t i = 0; i < m; i++)
{
if (i)
{
ans = max(ans, root_paths[i] + prefix_sum + dp1);
ans = max(ans, sum + root_paths[i] - prefix_sum + dp2);
}
dp1 = max(dp1, root_paths[i] - prefix_sum);
dp2 = max(dp2, root_paths[i] + prefix_sum);
prefix_sum += next_dis[i];
}
return ans;
}
void mark_component(unsigned u, vector<bool> &vis)
{
vis[u] = 1;
for (auto const &[v, w] : g[u])
if (!vis[v])
mark_component(v, vis);
}
bool edge_cmp(pair<unsigned, unsigned> const &a, pair<unsigned, unsigned> const &b)
{
return a.first == b.first;
}
int main()
{
size_t n;
cin >> n;
g = vector<vector<pair<unsigned, unsigned>>>(n);
for (size_t i = 0; i < n; i++)
{
unsigned u, w;
cin >> u >> w;
g[i].emplace_back(u - 1, w);
g[u - 1].emplace_back(i, w);
}
for (unsigned i = 0; i < n; i++)
{
sort(g[i].begin(), g[i].end(), greater<pair<unsigned, unsigned>>());
g[i].resize(unique(g[i].begin(), g[i].end(), edge_cmp) - g[i].begin());
sort(g[i].begin(), g[i].end());
}
vector<bool> vis(n, 0), cvis(n, 0);
int64_t max_distance = 0;
for (unsigned i = 0; i < n; i++)
{
if (!vis[i])
{
mark_component(i, vis);
max_distance += longest_simple_path(i, cvis);
}
}
cout << max_distance << '\n';
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |