#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdlib>
struct Edge
{
Edge(int s, int e, int c) : start(s), end(e), cost(c) {}
int start, end, cost;
};
const int MAXN = 1e3;
const int MAXM = 1 << 10;
const int MAXD = 10;
const int INFTY = 1e9;
std::vector<int> spanningTree[MAXN];
std::vector<Edge> canRemove;
int depth[MAXN];
int parent[MAXN];
int parSt[MAXN];
int strees[MAXN];
int chd[MAXN][MAXD + 1];
std::vector<Edge> graph[MAXN];
int dp[MAXN][MAXD + 1];
int trans[MAXN][MAXD][MAXD + 1];
int bitdp[MAXN][MAXM];
void calcdepth(int node)
{
for (int child : spanningTree[node])
if (child != parent[node])
{
depth[child] = depth[node] + 1;
parent[child] = node;
chd[node][strees[node]] = child;
parSt[child] = strees[node]++;
calcdepth(child);
}
}
int lca(int u, int v)
{
while (depth[u] > depth[v])
u = parent[u];
while (depth[u] < depth[v])
v = parent[v];
while (u != v)
{
u = parent[u];
v = parent[v];
}
return u;
}
std::pair<int, int> getw(int node, int stop, int from)
{
int offset = 0;
if (from != MAXD)
offset = dp[chd[node][from]][MAXD];
if (node == stop)
return { -offset, from };
std::pair<int, int> w = getw(parent[node], stop, parSt[node]);
return { w.first + dp[node][from] - offset, w.second };
}
void compute(int node)
{
bitdp[node][0] = 0;
for (int child : spanningTree[node])
if (child != parent[node])
{
compute(child);
bitdp[node][0] += dp[child][MAXD];
}
for (Edge &edge : graph[node])
{
std::pair<int, int> left = getw(edge.start, node, MAXD);
std::pair<int, int> right = getw(edge.end, node, MAXD);
int froml = std::min(left.second, right.second);
int fromr = std::max(left.second, right.second);
trans[node][froml][fromr] = std::min(trans[node][froml][fromr], left.first + right.first - edge.cost);
bitdp[node][0] += edge.cost;
}
int masks = 1 << strees[node];
for (int iMask = 1; iMask < masks; iMask++)
{
int last = 31 - __builtin_clz(iMask);
bitdp[node][iMask] = std::min(bitdp[node][iMask], bitdp[node][iMask ^ (1 << last)] + trans[node][last][MAXD]);
for (int iBit = 0; iBit < last; iBit++)
if ((iMask >> iBit) & 1)
bitdp[node][iMask] = std::min(bitdp[node][iMask], bitdp[node][iMask ^ (1 << last) ^ (1 << iBit)] + trans[node][iBit][last]);
}
for (int iTree = 0; iTree < strees[node]; iTree++)
for (int iMask = 0; iMask < masks; iMask++)
if (((iMask >> iTree) & 1) == 0)
dp[node][iTree] = std::min(dp[node][iTree], bitdp[node][iMask]);
for (int iMask = 0; iMask < masks; iMask++)
dp[node][MAXD] = std::min(dp[node][MAXD], bitdp[node][iMask]);
}
int main()
{
std::ios::sync_with_stdio(false);
std::cout.tie(nullptr);
std::cin.tie(nullptr);
int nodes, edges;
std::cin >> nodes >> edges;
for (int iEdge = 0; iEdge < edges; iEdge++)
{
int start, end, cost;
std::cin >> start >> end >> cost;
start--; end--;
if (cost == 0)
{
spanningTree[start].emplace_back(end);
spanningTree[end].emplace_back(start);
}
else
{
canRemove.emplace_back(start, end, cost);
}
}
calcdepth(0);
std::fill_n((int *)dp, MAXN * (MAXD + 1), INFTY);
std::fill_n((int *)trans, MAXN * MAXD * (MAXD + 1), INFTY);
std::fill_n((int *)bitdp, MAXN * MAXM, INFTY);
int obligCost = 0;
for (Edge &edge : canRemove)
{
if (std::abs(depth[edge.start] - depth[edge.end]) % 2 == 1)
obligCost += edge.cost;
else
{
int anc = lca(edge.start, edge.end);
graph[anc].emplace_back(edge.start, edge.end, edge.cost);
}
}
compute(0);
std::cout << obligCost + dp[0][MAXD] << '\n';
return 0;
}
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
6 ms |
4860 KB |
Output is correct |
2 |
Correct |
6 ms |
4856 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
6 ms |
4856 KB |
Output is correct |
2 |
Correct |
6 ms |
4860 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
10 ms |
5112 KB |
Output is correct |
2 |
Correct |
10 ms |
5112 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
6 ms |
4856 KB |
Output is correct |
2 |
Correct |
6 ms |
4856 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
6 ms |
4856 KB |
Output is correct |
2 |
Correct |
6 ms |
4856 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
6 ms |
4860 KB |
Output is correct |
2 |
Correct |
6 ms |
4856 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
6 ms |
4856 KB |
Output is correct |
2 |
Correct |
7 ms |
4984 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
7 ms |
4984 KB |
Output is correct |
2 |
Correct |
7 ms |
4984 KB |
Output is correct |
3 |
Correct |
7 ms |
4984 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
8 ms |
5112 KB |
Output is correct |
2 |
Correct |
9 ms |
5112 KB |
Output is correct |
3 |
Correct |
8 ms |
5096 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
8 ms |
5068 KB |
Output is correct |
2 |
Correct |
8 ms |
4984 KB |
Output is correct |
3 |
Correct |
16 ms |
5140 KB |
Output is correct |
4 |
Correct |
9 ms |
4984 KB |
Output is correct |
# |
결과 |
실행 시간 |
메모리 |
Grader output |
1 |
Correct |
11 ms |
5112 KB |
Output is correct |
2 |
Correct |
18 ms |
5116 KB |
Output is correct |
3 |
Correct |
12 ms |
5112 KB |
Output is correct |
4 |
Correct |
9 ms |
5112 KB |
Output is correct |