#include <bits/stdc++.h>
using namespace std;
struct Edge
{
unsigned u, v, w;
};
vector<vector<unsigned>> g, anc;
vector<unsigned> height, ind;
vector<vector<Edge>> unpaved;
vector<vector<unsigned>> dp;
unsigned lift(unsigned u, unsigned h)
{
unsigned z = 0;
while (h)
{
if (h & 1)
{
assert(z < anc[u].size());
u = anc[u][z];
}
h >>= 1;
z++;
}
return u;
}
unsigned lca(unsigned u, unsigned v)
{
assert(u < g.size() && v < g.size());
if (height[u] < height[v])
swap(u, v);
u = lift(u, height[u] - height[v]);
if (u == v)
return u;
for (unsigned i = anc[u].size() - 1; i < anc[u].size(); i--)
{
if (anc[u][i] != anc[v][i])
{
u = anc[u][i];
v = anc[v][i];
}
}
return anc[u][0];
}
void traverse(unsigned u, vector<unsigned> &path, unsigned p = -1, unsigned h = 0)
{
for (unsigned i = 1; i <= path.size(); i <<= 1U)
anc[u].push_back(path[path.size() - i]);
height[u] = h;
path.push_back(u);
for (unsigned const &v : g[u])
if (v != p)
traverse(v, path, u, h + 1);
path.pop_back();
}
void calc_dp(unsigned u)
{
for (unsigned const &v : g[u])
{
calc_dp(v);
}
dp[u] = vector<unsigned>(1U << g[u].size());
// Case 1. Just delete the root and add up subtree values.
for (unsigned z = 0; z < (1U << g[u].size()); z++)
{
dp[u][z] = 0;
for (unsigned i = 0; i < g[u].size(); i++)
{
if (!(z & (1U << i)))
{
dp[u][z] += dp[g[u][i]][0];
}
}
}
for (unsigned i = 0; i < g[u].size(); i++)
{
ind[g[u][i]] = i;
}
// Case 2: Take exactly one unpaved road whose tree path contains u.
for (auto const &[a, b, w] : unpaved[u])
{
// Stores just the value obtained from the two used subtrees.
unsigned x = 0;
if (a != u)
{
x += dp[a][0];
unsigned r = a, s = anc[a][0];
while (s != u)
{
// assert(dp[s].size() == 1U << g[s].size());
x += dp[s][1U << ind[r]];
r = s;
s = anc[s][0];
}
}
if (b != u)
{
x += dp[b][0];
unsigned r = b, s = anc[b][0];
while (s != u)
{
x += dp[s][1U << ind[r]];
r = s;
s = anc[s][0];
}
}
unsigned p = UINT_MAX, q = UINT_MAX;
if (a != u)
p = ind[lift(a, height[a] - height[u] - 1)];
if (b != u)
q = ind[lift(b, height[b] - height[u] - 1)];
for (unsigned z = 0; z < (1U << g[u].size()); z++)
{
if ((a != u && (z & (1U << p))) || (b != u && (z & (1U << q))))
continue;
unsigned y = 0;
// Sum all children not on an edge path and not ruled out.
for (unsigned i = 0; i < g[u].size(); i++)
{
if (!(z & (1U << i)) && i != p && i != q)
{
y += dp[g[u][i]][0];
}
}
dp[u][z] = max(dp[u][z], x + y + w);
}
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
size_t n, m;
cin >> n >> m;
g = vector<vector<unsigned>>(n);
vector<Edge> unpaved_edges;
unsigned total_cost = 0;
for (size_t i = 0; i < m; i++)
{
unsigned u, v, w;
cin >> u >> v >> w;
total_cost += w;
if (!w)
{
g[u - 1].push_back(v - 1);
g[v - 1].push_back(u - 1);
}
else
{
unpaved_edges.push_back({u - 1, v - 1, w});
}
}
height = vector<unsigned>(n);
anc = vector<vector<unsigned>>(n);
vector<unsigned> path;
traverse(0, path);
for (unsigned u = 0; u < n; u++)
{
for (auto it = g[u].begin(); it != g[u].end(); it++)
{
if (!anc[u].empty() && *it == anc[u][0])
{
g[u].erase(it);
break;
}
}
}
unpaved = vector<vector<Edge>>(n);
for (auto const &[u, v, w] : unpaved_edges)
{
if (!((height[u] + height[v]) & 1))
{
assert(lca(u, v) < n);
unpaved[lca(u, v)].push_back({u, v, w});
}
}
dp = vector<vector<unsigned>>(n);
ind = vector<unsigned>(n);
calc_dp(0);
cout << total_cost - dp[0][0] << '\n';
}
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
0 ms |
212 KB |
Output is correct |
2 |
Correct |
1 ms |
212 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
1 ms |
212 KB |
Output is correct |
2 |
Correct |
1 ms |
212 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Runtime error |
2 ms |
980 KB |
Execution killed with signal 11 |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Incorrect |
1 ms |
212 KB |
Output isn't correct |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Incorrect |
1 ms |
212 KB |
Output isn't correct |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Incorrect |
1 ms |
340 KB |
Output isn't correct |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Incorrect |
1 ms |
340 KB |
Output isn't correct |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Incorrect |
2 ms |
468 KB |
Output isn't correct |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Runtime error |
5 ms |
1108 KB |
Execution killed with signal 11 |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Incorrect |
14 ms |
532 KB |
Output isn't correct |
2 |
Halted |
0 ms |
0 KB |
- |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Runtime error |
8 ms |
1164 KB |
Execution killed with signal 11 |
2 |
Halted |
0 ms |
0 KB |
- |