結果
問題 | No.2678 Minmax Independent Set (Hack) |
ユーザー | NokonoKotlin |
提出日時 | 2024-02-11 20:18:05 |
言語 | C++23 (gcc 12.3.0 + boost 1.83.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 4,031 bytes |
コンパイル時間 | 2,720 ms |
コンパイル使用メモリ | 261,244 KB |
実行使用メモリ | 12,072 KB |
最終ジャッジ日時 | 2024-09-29 23:01:56 |
合計ジャッジ時間 | 3,298 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
ソースコード
#include <bits/stdc++.h> struct RNG { void setSeed(uint64_t seed) { seedSet = true; x = seed; } template <class T> T choice(std::vector<T>& v) { assert(!v.empty()); return v[range(0, (int)v.size() - 1)]; } template <class T> void shuffle(std::vector<T>& v) { const int N = v.size(); for (int i = 0; i < N - 1; i++) { const int j = range(i, N - 1); if (i == j) continue; std::swap(v[i], v[j]); } } // generate random integers in [from, to] template <class T, class U> typename std::common_type<T, U>::type range(T from, U to) { static_assert(std::is_integral_v<T>); static_assert(std::is_integral_v<U>); static_assert(std::is_integral_v<typename std::common_type<T, U>::type>); assert(from <= to); uint64_t width = to - from + 1; typename std::common_type<T, U>::type ret = from; ret += xorshift64() % width; return ret; } private: bool seedSet = false; uint64_t x; uint64_t xorshift64() { assert(seedSet); x ^= x << 13; x ^= x >> 7; x ^= x << 17; return x; } } rng; // 辺を 1 箇所張り替えて非連結にする using namespace std; //----NokonoKotlin library : UnionFind(n) , nは要素数----- class UnionFind { private: vector<long long> par; public: int Size; vector<long long> rank; // rankが高いほど上の親である vector<long long> size; // 配列の中身は0 ~ N-1 UnionFind() {} UnionFind(long long N) : rank(N), size(N) { Size = N; par.resize(N); for (int i = 0; i < Size; i++) par[i] = i; for (int i = 0; i < Size; i++) rank[i] = 0; for (int i = 0; i < Size; i++) size[i] = 1; } ~UnionFind() { Release(); } void Release() { if (par.size() == 0) { return; } } int root(int x) { if (par[x] == x) return x; else { par[x] = root(par[x]); return par[x]; } } void unite(int x, int y) { int rx = root(x); int ry = root(y); int S = size[ry] + size[rx]; if (rx == ry) return; if (rank[rx] < rank[ry]) { par[rx] = ry; // rankの高い方を親にする size[rx] = S; size[ry] = S; } else { par[ry] = rx; size[ry] = S; size[rx] = S; if (rank[rx] == rank[ry]) rank[rx]++; } } int getsize(int x) { return size[root(x)]; } bool same(int x, int y) { int rx = root(x); int ry = root(y); return rx == ry; } }; int main(int argc, char* argv[]) { rng.setSeed(372864312); int N = 100000; vector<pair<int, int>> edges; vector<int> prufer(N - 1); for (int i = 0; i < N - 2; i++) prufer[i] = rng.range(1, N - 1); prufer.back() = N; multiset<int> cands; for (int x = 1; x <= N; x++) cands.insert(x); for (int x : prufer) cands.erase(x); vector<int> cnt(N + 1, 0); for (int x : prufer) cnt[x]++; for (int x : prufer) { int child = *cands.begin(); edges.emplace_back(x, child); cands.erase(child); cnt[x]--; if (cnt[x] == 0) cands.insert(x); } UnionFind T(N + 1); // どこかで切って 2 つの連結成分にする edges.erase(edges.begin() + int(edges.size()) / 2); for (auto p : edges) T.unite(p.first, p.second); cout << N << endl; // 片方をなもりグラフにして終了 for (int x = 1; x < N; x++) { for (int y = x + 1; y <= N; y++) { if (T.same(x, y)) { edges.emplace_back(x, y); for (pair<int, int> p : edges) cout << min(p.first, p.second) << " " << max(p.first, p.second) << "\n"; return 0; } } } return 0; }