Skip to content

Commit 1de9ccf

Browse files
committed
feat: done the final problem
Signed-off-by: Certseeds <51754303+Certseeds@users.noreply.github.com>
1 parent 316127e commit 1de9ccf

4 files changed

Lines changed: 155 additions & 151 deletions

File tree

.github/workflows/pull_request.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,6 @@ jobs:
6565
working-directory: ./CMAKE_DEBUG_PATH/lab_00
6666
run: cmake --build . --config DEBUG --parallel
6767

68-
- name: cmake compile 2021F
69-
working-directory: ./CMAKE_DEBUG_PATH/2021F
70-
run: cmake --build . --config DEBUG --parallel
71-
7268
- name: cmake compile
7369
working-directory: ./CMAKE_DEBUG_PATH
7470
run: cmake --build . --config DEBUG --parallel

.github/workflows/release.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,6 @@ jobs:
5151
working-directory: ./CMAKE_DEBUG_PATH/lab_00
5252
run: cmake --build . --config DEBUG --parallel
5353

54-
- name: cmake compile 2021F
55-
working-directory: ./CMAKE_DEBUG_PATH/2021F
56-
run: cmake --build . --config DEBUG --parallel
57-
5854
- name: cmake compile
5955
working-directory: ./CMAKE_DEBUG_PATH
6056
run: cmake --build . --config DEBUG --parallel

lab_08/G/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# lab_08_G
22

3-
> TODO, 21组用例还是无法解决这个问题
3+
> 这个问题实际上是中国计算机学会 (CCF) 举办的 NOIP 2018 提高组 Day 1 的第三题《赛道修建》
44
55
## Description
66

lab_08/G/main.cpp

Lines changed: 154 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,62 @@
1-
// SPDX-License-Identifier: AGPL-3.0-or-later
2-
// SPDX-FileCopyrightText: 2020-2025 nanoseeds
3-
#include <algorithm>
4-
#include <cstdint>
5-
#include <cstdlib>
6-
#include <ctime>
7-
#include <iostream>
8-
#include <memory>
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: 2020-2026 Certseeds
3+
#include <list>
4+
#include <array>
5+
#include <deque>
6+
#include <queue>
7+
#include <stack>
98
#include <tuple>
9+
#include <string>
1010
#include <vector>
11+
#include <cstdint>
12+
#include <cstddef>
13+
#include <numeric>
14+
#include <iostream>
15+
#include <algorithm>
16+
#include <unordered_map>
17+
#include <unordered_set>
18+
19+
#ifndef ALGORITHM_TEST_MACRO
20+
#pragma GCC optimize(3, "Ofast", "inline", "no-stack-protector", "unroll-loops")
21+
#pragma GCC optimize("inline-small-functions")
22+
#pragma GCC optimize("-finline-small-functions")
23+
#pragma GCC target("tune=native")
24+
#else
25+
namespace lab_08_G {
26+
#endif
27+
28+
using std::cin;
29+
using std::tie;
30+
using std::cout;
31+
using std::list;
32+
using std::sort;
33+
using std::array;
34+
using std::deque;
35+
using std::queue;
36+
using std::stack;
37+
using std::tuple;
38+
using std::string;
39+
using std::vector;
40+
using std::unordered_map;
41+
using std::unordered_set;
42+
using std::priority_queue;
43+
static constexpr const char end{'\n'};
44+
45+
using num_t = int32_t;
1146

12-
namespace tree {
1347
struct Edge {
14-
int32_t to; // 边的终点
15-
int32_t next; // 同一个起点的下一条边的索引
16-
int64_t weight; // 边的权重
48+
int32_t to; // 边的终点
49+
int32_t next; // 同一个起点的下一条边的索引
50+
int64_t weight; // 边的权重
1751
};
1852

1953
class Graph {
20-
public:
54+
public:
2155
// 边的结构体定义
22-
std::vector<int32_t> head; // head[i] 存储顶点i的第一条边的索引
23-
std::vector<Edge> edges; // 存储所有边的数组
24-
int32_t edge_count; // 当前边的总数
25-
public:
56+
std::vector<int32_t> head; // head[i] 存储顶点i的第一条边的索引
57+
std::vector<Edge> edges; // 存储所有边的数组
58+
int32_t edge_count; // 当前边的总数
59+
public:
2660
/**
2761
* @brief 构造函数
2862
* @param num_nodes 顶点的数量 (假设顶点编号从 1 到 num_nodes)
@@ -64,154 +98,133 @@ class Graph {
6498
add_edge(v, u, w);
6599
}
66100
};
67-
}
68101

69-
#ifndef ALGORITHM_TEST_MACRO
70-
#pragma GCC optimize(3, "Ofast", "inline", "no-stack-protector", "unroll-loops")
71-
#pragma GCC optimize("inline-small-functions")
72-
#pragma GCC optimize("-finline-small-functions")
73-
#pragma GCC target("tune=native")
74-
#else
75-
namespace lab_08_G {
76-
#endif
77-
using std::cin;
78-
using std::cout;
79-
using std::tuple;
80-
using std::vector;
81-
static constexpr const char end{'\n'};
102+
using input_type = tuple<int, int, Graph>;
103+
using output_type = num_t;
82104

83-
using i32 = int32_t;
84-
using i64 = int64_t;
85-
struct ProblemInput {
86-
i32 n;
87-
i32 m;
88-
std::shared_ptr<tree::Graph> graph;
89-
i64 total_weight;
90-
};
105+
inline input_type read();
91106

92-
using ProblemOutput = i64;
107+
output_type cal(input_type data);
93108

94-
ProblemInput read_input();
95-
ProblemOutput solve(const ProblemInput &in);
96-
void write_output(const ProblemOutput &out);
97-
static bool can_form_paths(const ProblemInput &in, const i64 limit);
109+
void output(const output_type &data);
98110

99111
int main() {
100-
const auto in = read_input();
101-
const auto out = solve(in);
102-
write_output(out);
112+
const auto input_data = read();
113+
const auto output_data = cal(input_data);
114+
output(output_data);
103115
return 0;
104116
}
105117

106-
ProblemInput read_input() {
107-
ProblemInput in;
108-
std::cin >> in.n >> in.m;
109-
int32_t u;
110-
int32_t v;
111-
int64_t w;
112-
in.graph = std::make_shared<tree::Graph>(in.n, static_cast<int32_t>((in.n - 1) * 2));
113-
in.total_weight = 0;
114-
for (i32 i = 0; i < in.n - 1; ++i) {
115-
std::cin >> u >> v >> w;
116-
in.graph->add_undirected_edge(u, v, w);
117-
in.total_weight += w;
118-
}
119-
return in;
120-
}
121-
122-
123-
ProblemOutput solve(const ProblemInput &in) {
124-
i64 left = 0;
125-
i64 right = in.total_weight;
126-
i64 answer = 0;
127-
while (left <= right) {
128-
const auto mid = (left + right) >> 1;
129-
if (can_form_paths(in, mid)) {
130-
answer = mid;
131-
left = mid + 1;
132-
} else {
133-
right = mid - 1;
134-
}
118+
inline input_type read() {
119+
int n, m;
120+
cin >> n >> m;
121+
Graph adj(n, (n - 1) * 2);
122+
for (int i = 0; i < n - 1; ++i) {
123+
int u, v, w;
124+
cin >> u >> v >> w;
125+
adj.add_undirected_edge(u, v, w);
135126
}
136-
return answer;
127+
return std::make_tuple(n, m, adj);
137128
}
138129

139-
void write_output(const ProblemOutput &out) {
140-
std::cout << out << end;
141-
}
130+
namespace {
131+
struct Solver {
132+
int n, m;
133+
const Graph &adj;
134+
int cnt;
135+
int mid;
142136

143-
static bool can_form_paths(const ProblemInput &in, const i64 limit) {
144-
if (limit <= 0) return true;
145-
const auto &graph = *in.graph;
146-
const auto n = in.n;
147-
std::vector<int32_t> parent(static_cast<size_t>(n + 1), 0);
148-
std::vector<int32_t> order;
149-
order.reserve(static_cast<size_t>(n));
150-
std::vector<int32_t> stack;
151-
stack.reserve(static_cast<size_t>(n));
152-
stack.push_back(1);
153-
parent[1] = 0;
154-
while (!stack.empty()) {
155-
const auto u = stack.back();
156-
stack.pop_back();
157-
order.push_back(u);
158-
for (auto ei = graph.head[static_cast<size_t>(u)]; ei != -1; ei = graph.edges[static_cast<size_t>(ei)].next) {
159-
const auto &edge = graph.edges[static_cast<size_t>(ei)];
160-
if (edge.to == parent[static_cast<size_t>(u)]) continue;
161-
parent[static_cast<size_t>(edge.to)] = u;
162-
stack.push_back(edge.to);
163-
}
137+
Solver(const int n, const int m, const Graph &adj) : n(n), m(m), adj(adj), cnt(0), mid(0) {
164138
}
165-
std::vector<i64> dp(static_cast<size_t>(n + 1), 0);
166-
int32_t formed = 0;
167-
std::vector<i64> lengths;
168-
std::vector<bool> used;
169-
170-
for (auto it = order.rbegin(); it != order.rend(); ++it) {
171-
const auto u = *it;
172-
lengths.clear();
173-
for (auto ei = graph.head[static_cast<size_t>(u)]; ei != -1; ei = graph.edges[static_cast<size_t>(ei)].next) {
174-
const auto &edge = graph.edges[static_cast<size_t>(ei)];
175-
if (parent[static_cast<size_t>(u)] == edge.to) continue;
176-
lengths.push_back(dp[static_cast<size_t>(edge.to)] + edge.weight);
177-
}
178-
179-
std::sort(lengths.rbegin(), lengths.rend());
180139

181-
used.assign(lengths.size(), false);
182-
int32_t l = 0;
183-
int32_t r = static_cast<int32_t>(lengths.size()) - 1;
184-
185-
while (l < r) {
186-
if (used[l]) {
187-
l++;
140+
int dfs(const int u, const int p) {
141+
vector<int> vec;
142+
for (int i = adj.head[u]; i != -1; i = adj.edges[i].next) {
143+
const auto &e = adj.edges[i];
144+
if (e.to == p) {
188145
continue;
189146
}
190-
while (l < r && (used[r] || lengths[l] + lengths[r] < limit)) {
191-
r--;
192-
}
193-
if (l < r) {
194-
formed++;
195-
used[l] = used[r] = true;
196-
l++;
197-
r--;
147+
const int len = dfs(e.to, u) + e.weight;
148+
if (len >= mid) {
149+
cnt++;
150+
} else {
151+
vec.push_back(len);
198152
}
199153
}
200-
201-
i64 carry = 0;
202-
for(size_t i = 0; i < lengths.size(); ++i) {
203-
if (!used[i]) {
204-
if (lengths[i] >= limit) {
205-
formed++;
206-
used[i] = true;
154+
sort(vec.begin(), vec.end());
155+
156+
auto calc = [&](int skip) {
157+
int c = 0;
158+
int l = 0, r = (int) vec.size() - 1;
159+
while (l < r) {
160+
if (l == skip) {
161+
l++;
162+
continue;
163+
}
164+
if (r == skip) {
165+
r--;
166+
continue;
167+
}
168+
if (vec[l] + vec[r] >= mid) {
169+
c++;
170+
l++;
171+
r--;
207172
} else {
208-
carry = std::max(carry, lengths[i]);
173+
l++;
209174
}
210175
}
176+
return c;
177+
};
178+
179+
const int base = calc(-1);
180+
cnt += base;
181+
182+
int l = 0, r = (int) vec.size() - 1;
183+
int ans_idx = -1;
184+
while (l <= r) {
185+
const int mid_idx = l + (r - l) / 2;
186+
if (calc(mid_idx) == base) {
187+
ans_idx = mid_idx;
188+
l = mid_idx + 1;
189+
} else {
190+
r = mid_idx - 1;
191+
}
192+
}
193+
194+
if (ans_idx != -1) return vec[ans_idx];
195+
return 0;
196+
}
197+
198+
bool check(int k) {
199+
mid = k;
200+
cnt = 0;
201+
dfs(1, 0);
202+
return cnt >= m;
203+
}
204+
};
205+
}
206+
207+
output_type cal(input_type data) {
208+
const int n = std::get<0>(data);
209+
const int m = std::get<1>(data);
210+
const Graph &adj = std::get<2>(data);
211+
Solver solver(n, m, adj);
212+
int l = 1, r = 500000000;
213+
int ans = 0;
214+
while (l <= r) {
215+
const int mid = l + (r - l) / 2;
216+
if (solver.check(mid)) {
217+
ans = mid;
218+
l = mid + 1;
219+
} else {
220+
r = mid - 1;
211221
}
212-
dp[static_cast<size_t>(u)] = carry;
213222
}
214-
return formed >= in.m;
223+
return ans;
224+
}
225+
226+
void output(const output_type &data) {
227+
cout << data << end;
215228
}
216229

217230
static const auto faster_streams = [] {
@@ -225,7 +238,6 @@ static const auto faster_streams = [] {
225238
// 关闭c++风格输入输出 , 与C风格输入输出的同步,提高性能.
226239
return 0;
227240
}();
228-
229241
#ifdef ALGORITHM_TEST_MACRO
230242
}
231243
#endif

0 commit comments

Comments
 (0)