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 {
1347struct 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
1953class 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
99111int 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
217230static 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