結果

問題 No.922 東北きりきざむたん
ユーザー kimiyuki
提出日時 2019-11-09 10:50:29
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
AC  
実行時間 261 ms / 2,000 ms
コード長 5,445 bytes
コンパイル時間 2,957 ms
コンパイル使用メモリ 217,240 KB
最終ジャッジ日時 2025-01-08 03:44:56
ジャッジサーバーID
(参考情報)
judge3 / judge5
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 4
other AC * 26
権限があれば一括ダウンロードができます

ソースコード

diff #
プレゼンテーションモードにする

#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; (i) < (int)(n); ++ (i))
using namespace std;
template <class T, class U> inline void chmin(T & a, U const & b) { a = min<T>(a, b); }
/**
* @brief sparse table on a semilattice
* @note a semilattice is a commutative idempotent semigroup
* @note for convenience, it requires the unit
* @note O(N log N) space
*/
template <class Semilattice>
struct sparse_table {
typedef typename Semilattice::value_type value_type;
std::vector<std::vector<value_type> > table;
Semilattice lat;
sparse_table() = default;
/**
* @note O(N \log N) time
*/
sparse_table(std::vector<value_type> const & data, Semilattice const & a_lat = Semilattice())
: lat(a_lat) {
int n = data.size();
int log_n = 32 - __builtin_clz(n);
table.resize(log_n, std::vector<value_type>(n));
table[0] = data;
REP (k, log_n - 1) {
REP (i, n) {
table[k + 1][i] = i + (1ll << k) < n ?
lat.append(table[k][i], table[k][i + (1ll << k)]) :
table[k][i];
}
}
}
/**
* @note O(1)
*/
value_type range_concat(int l, int r) const {
if (l == r) return lat.unit(); // if there is no unit, remove this line
assert (0 <= l and l < r and r <= table[0].size());
int k = 31 - __builtin_clz(r - l); // log2
return lat.append(table[k][l], table[k][r - (1ll << k)]);
}
};
struct indexed_min_semilattice {
typedef std::pair<int, int> value_type;
value_type unit() const { return { INT_MAX, INT_MAX }; }
value_type append(value_type a, value_type b) const { return std::min(a, b); }
};
/**
* @brief lowest common ancestor with \pm 1 RMQ and sparse table
* @see https://www.slideshare.net/yumainoue965/lca-and-rmq
* @note verified http://www.utpc.jp/2011/problems/travel.html
*/
struct lowest_common_ancestor_for_forest {
sparse_table<indexed_min_semilattice> table;
std::vector<int> index;
lowest_common_ancestor_for_forest() = default;
/**
* @note O(N)
* @param g is an adjacent list of a tree
*/
lowest_common_ancestor_for_forest(std::vector<std::vector<int> > const & g) {
std::vector<std::pair<int, int> > tour;
index.assign(g.size(), -1);
REP (root, g.size()) if (index[root] == -1) {
dfs(root, -1, 0, g, tour);
tour.emplace_back(-1, -1);
}
table = sparse_table<indexed_min_semilattice>(tour);
}
private:
/**
* @note to avoid stack overflow
*/
void dfs(int x, int parent, int depth, std::vector<std::vector<int> > const & g, std::vector<std::pair<int, int> > & tour) {
index[x] = tour.size();
tour.emplace_back(depth, x);
for (int y : g[x]) if (y != parent) {
dfs(y, x, depth + 1, g, tour);
tour.emplace_back(depth, x);
}
}
public:
/**
* @note O(1)
*/
int operator () (int x, int y) const {
assert (0 <= x and x < index.size());
assert (0 <= y and y < index.size());
x = index[x];
y = index[y];
if (x > y) std::swap(x, y);
return table.range_concat(x, y + 1).second;
}
int get_depth(int x) const {
assert (0 <= x and x < index.size());
return table.range_concat(index[x], index[x] + 1).first;
}
bool is_in_same_tree(int x, int y) const {
return (*this)(x, y) != -1;
}
int get_dist(int x, int y) const {
assert (0 <= x and x < index.size());
assert (0 <= y and y < index.size());
int z = (*this)(x, y);
return get_depth(x) + get_depth(y) - 2 * get_depth(z);
}
};
int64_t solve(int n, int m, int q, const vector<vector<int> > & g, const vector<int> & a, const vector<int> & b) {
lowest_common_ancestor_for_forest lca(g);
int64_t answer = 0;
vector<int> cnt(n);
REP (i, q) {
if (lca.is_in_same_tree(a[i], b[i])) {
answer += lca.get_dist(a[i], b[i]);
} else {
++ cnt[a[i]];
++ cnt[b[i]];
}
}
vector<int64_t> imos(n);
REP (root, n) if (lca.get_depth(root) == 0) {
int sum_cnt = 0;
function<int (int, int, int)> go1 = [&](int x, int parent, int depth) {
sum_cnt += cnt[x];
imos[root] += depth * cnt[x];
int k = cnt[x];
for (int y : g[x]) if (y != parent) {
k += go1(y, x, depth + 1);
}
if (x != root) {
imos[x] += - 2 * k;
}
return k;
};
go1(root, -1, 0);
int64_t min_cost = INT64_MAX;
function<void (int, int)> go2 = [&](int x, int parent) {
chmin(min_cost, imos[x]);
for (int y : g[x]) if (y != parent) {
imos[y] += imos[x] + sum_cnt;
go2(y, x);
}
};
go2(root, -1);
answer += min_cost;
}
return answer;
}
int main() {
int n, m, q; cin >> n >> m >> q;
vector<vector<int> > g(n);
REP (i, m) {
int u, v; cin >> u >> v;
-- u;
-- v;
g[u].push_back(v);
g[v].push_back(u);
}
vector<int> a(q), b(q);
REP (i, q) {
cin >> a[i] >> b[i];
-- a[i];
-- b[i];
}
cout << solve(n, m, q, g, a, b) << endl;
return 0;
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
0