結果
| 問題 |
No.1639 最小通信路
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2021-08-06 22:32:53 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 26 ms / 2,000 ms |
| コード長 | 3,440 bytes |
| コンパイル時間 | 5,765 ms |
| コンパイル使用メモリ | 412,748 KB |
| 最終ジャッジ日時 | 2025-01-23 15:54:28 |
|
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 43 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
#define overload3(_1, _2, _3, name, ...) name
#define rep1(n) for (decltype(n) _tmp = 0; _tmp < (n); _tmp++)
#define rep2(i, n) for (decltype(n) i = 0; i < (n); i++)
#define rep3(i, a, b) for (decltype(b) i = a; i < (b); i++)
#define rep(...) overload3(__VA_ARGS__, rep3, rep2, rep1)(__VA_ARGS__)
#if __has_include(<debug.hpp>)
#include <debug.hpp>
#else
#define dbg(...) (void(0))
#endif
struct IOSetup {
IOSetup() noexcept {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout << fixed << setprecision(10);
cerr << fixed << setprecision(10);
}
} iosetup;
template<class T> void drop(const T &x) {
cout << x << "\n";
exit(0);
}
template<class T> bool chmax(T &a, const T &b) { return a < b and (a = b, true); }
template<class T> bool chmin(T &a, const T &b) { return a > b and (a = b, true); }
using i64 = long long;
using f64 = long double;
#include <boost/multiprecision/cpp_int.hpp>
using Bint = boost::multiprecision::cpp_int;
/**
* @brief Union Find
* @note a.k.a DSU; Disjoint Set Union
*/
struct UnionFind {
vector<int> parents_or_size;
UnionFind(int size_):
parents_or_size(size_, -1) {}
bool unite(int u, int v) {
u = root(u), v = root(v);
if (u == v) return false;
if (parents_or_size[u] > parents_or_size[v]) swap(u, v);
parents_or_size[u] += parents_or_size[v];
parents_or_size[v] = u;
return true;
}
int root(int k) { return parents_or_size[k] < 0 ? k : parents_or_size[k] = root(parents_or_size[k]); }
int size(int k) { return -parents_or_size[root(k)]; }
bool same(int u, int v) { return root(u) == root(v); }
vector<vector<int>> groups() {
size_t n = parents_or_size.size();
vector<vector<int>> ret(n);
rep(i, n) ret[root(i)].emplace_back(i);
ret.erase(remove_if(begin(ret), end(ret), [&](const vector<int> &v) { return v.empty(); }));
return ret;
}
};
/**
* @brief Kruskal's Algorithm
* @note Solve MST; Minimum Spanning Tree in $O(|E|log|E)$.
* @note The sum of the weights of the edges can be obtained from
* ```accumulate(begin(ret), end(ret), 0, [](T acc, auto e) { return acc + get<2>(e); })```.
* @return Set of edges by vector<tuple<u, v, weight>>
*/
template<typename T> vector<tuple<size_t, size_t, T>> kruskal(vector<vector<pair<size_t, T>>> const &graph) {
using Edge = tuple<size_t, size_t, T>;
vector<Edge> edges{};
size_t n = size(graph);
if (n == 1) return {};
rep(i, n) for (const auto &[j, cost]: graph[i]) edges.emplace_back(Edge{i, j, cost});
sort(begin(edges), end(edges), [](Edge a, Edge b) { return get<2>(a) < get<2>(b); });
UnionFind uf(n);
vector<Edge> ret{};
for (const auto &[u, v, cost]: edges) {
if (not uf.same(u, v)) {
ret.emplace_back(Edge{u, v, cost});
uf.unite(u, v);
}
if (size(ret) == n - 1) break;
}
return ret;
}
int main() {
size_t n;
cin >> n;
vector graph(n, vector<pair<size_t, Bint>>{});
rep(n * (n - 1) / 2) {
size_t a, b;
Bint c;
cin >> a >> b >> c;
graph[--a].emplace_back(pair{--b, c});
graph[b].emplace_back(pair{a, c});
}
auto edges = kruskal(graph);
Bint ans = get<2>(edges.front());
for (const auto &[a, b, c]: edges) chmax(ans, c);
cout << ans << "\n";
}