結果
| 問題 |
No.1293 2種類の道路
|
| コンテスト | |
| ユーザー |
KoD
|
| 提出日時 | 2020-11-20 22:13:41 |
| 言語 | C++17(gcc12) (gcc 12.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 129 ms / 2,000 ms |
| コード長 | 4,036 bytes |
| コンパイル時間 | 3,623 ms |
| コンパイル使用メモリ | 134,044 KB |
| 最終ジャッジ日時 | 2025-01-16 02:27:18 |
|
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 2 |
| other | AC * 22 |
ソースコード
#line 1 "main.cpp"
/**
* @title Template
*/
#include <iostream>
#include <algorithm>
#include <utility>
#include <numeric>
#include <vector>
#include <array>
#include <cassert>
#include <stack>
#include <map>
#line 2 "/Users/kodamankod/Desktop/cpp_programming/Library/other/chmin_chmax.cpp"
template <class T, class U>
constexpr bool chmin(T &lhs, const U &rhs) {
if (lhs > rhs) { lhs = rhs; return true; }
return false;
}
template <class T, class U>
constexpr bool chmax(T &lhs, const U &rhs) {
if (lhs < rhs) { lhs = rhs; return true; }
return false;
}
/**
* @title Chmin/Chmax
*/
#line 2 "/Users/kodamankod/Desktop/cpp_programming/Library/other/range.cpp"
#line 4 "/Users/kodamankod/Desktop/cpp_programming/Library/other/range.cpp"
class range {
struct iter {
std::size_t itr;
constexpr iter(std::size_t pos) noexcept: itr(pos) { }
constexpr void operator ++ () noexcept { ++itr; }
constexpr bool operator != (iter other) const noexcept { return itr != other.itr; }
constexpr std::size_t operator * () const noexcept { return itr; }
};
struct reviter {
std::size_t itr;
constexpr reviter(std::size_t pos) noexcept: itr(pos) { }
constexpr void operator ++ () noexcept { --itr; }
constexpr bool operator != (reviter other) const noexcept { return itr != other.itr; }
constexpr std::size_t operator * () const noexcept { return itr; }
};
const iter first, last;
public:
constexpr range(std::size_t first, std::size_t last) noexcept: first(first), last(std::max(first, last)) { }
constexpr iter begin() const noexcept { return first; }
constexpr iter end() const noexcept { return last; }
constexpr reviter rbegin() const noexcept { return reviter(*last - 1); }
constexpr reviter rend() const noexcept { return reviter(*first - 1); }
};
/**
* @title Range
*/
#line 18 "main.cpp"
using i32 = std::int32_t;
using i64 = std::int64_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using isize = std::ptrdiff_t;
using usize = std::size_t;
constexpr i32 inf32 = (i32(1) << 30) - 1;
constexpr i64 inf64 = (i64(1) << 62) - 1;
struct UnionFind {
std::vector<isize> data;
std::stack<std::pair<usize, isize>> memo;
UnionFind(const usize N): data(N, -1) { }
usize find_untracked(usize x) {
if (data[x] < 0) return x;
return data[x] = find_untracked(data[x]);
}
usize find_tracked(usize x) {
while (data[x] >= 0) x = data[x];
return x;
}
void merge_untracked(usize x, usize y) {
x = find_untracked(x);
y = find_untracked(y);
if (x == y) return;
if (data[x] > data[y]) std::swap(x, y);
data[x] += data[y];
data[y] = x;
}
usize merge_tracked(usize x, usize y) {
x = find_tracked(x);
y = find_tracked(y);
if (x == y) return x;
if (data[x] > data[y]) std::swap(x, y);
memo.emplace(x, data[x]);
memo.emplace(y, data[y]);
data[x] += data[y];
data[y] = x;
return x;
}
bool same_untracked(usize x, usize y) {
x = find_untracked(x);
y = find_untracked(y);
return x == y;
}
bool same_tracked(usize x, usize y) {
x = find_tracked(x);
y = find_tracked(y);
return x == y;
}
void rollback() {
while (!memo.empty()) {
const auto [i, v] = memo.top();
memo.pop();
data[i] = v;
}
}
};
int main() {
usize N;
usize A, B;
std::cin >> N >> A >> B;
UnionFind d1(N);
while (A--) {
usize a, b;
std::cin >> a >> b;
--a; --b;
d1.merge_untracked(a, b);
}
UnionFind d2(N);
while (B--) {
usize a, b;
std::cin >> a >> b;
--a; --b;
d2.merge_untracked(a, b);
}
std::map<usize, std::vector<usize>> map;
for (auto i: range(0, N)) {
map[d1.find_untracked(i)].push_back(i);
}
u64 ans = 0;
for (const auto &[p, vec]: map) {
for (auto x: vec) {
d2.merge_tracked(x, vec[0]);
}
u64 s = -d1.data[p];
u64 t = -d2.data[d2.find_tracked(vec[0])];
d2.rollback();
ans += s * t - s;
}
std::cout << ans << '\n';
return 0;
}
KoD