結果
| 問題 |
No.922 東北きりきざむたん
|
| コンテスト | |
| ユーザー |
algon_320
|
| 提出日時 | 2019-11-08 22:14:02 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 166 ms / 2,000 ms |
| コード長 | 6,044 bytes |
| コンパイル時間 | 2,261 ms |
| コンパイル使用メモリ | 188,544 KB |
| 実行使用メモリ | 43,196 KB |
| 最終ジャッジ日時 | 2024-09-15 01:34:04 |
| 合計ジャッジ時間 | 5,668 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 26 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define stoi stoll
using pii=pair<int,int>;
using vi = vector<int>;
using vvi = vector<vi>;
#define all(c) begin(c),end(c)
#define rall(c) rbegin(c),rend(c)
#define fore(x,c) for(auto &&x:c)
#define rep(i,a,n) for(int i=a,i##len=(int)(n);i<i##len;++i)
#define rrep(i, a, n) for(int i=(int)(n-1);i>=a;--i)
#define sz(c) ((int)c.size())
#define contains(c,x) (c.find(x)!=end(c))
#define inseg(l,x,r) ((l)<=(x)&&(x)<(r))
#define dump(...)
#define pb push_back
#define _ 0
const signed INF_=1001001001; const long long INF=1001001001001001001LL;
const int DX[9]={0,1,0,-1,1,1,-1,-1,0},DY[9]={-1,0,1,0,-1,1,1,-1,0};
template<class T> ostream& operator<<(ostream &os,const vector<T> &v) {
for (auto i = begin(v); i != end(v); i++) os<<*i<<(i==end(v)-1?"":" ");return os;}
template<class T> istream& operator>>(istream &is,vector<T> &v) {
for (auto i = begin(v); i != end(v); i++) is>>*i;return is;}
template<class T,class U> istream& operator>>(istream &is, pair<T,U> &p) {
is>>p.first>>p.second;return is;}
template<class T, class U> bool chmax(T &a,const U &b){return a<b?a=b,1:0;}
template<class T, class U> bool chmin(T &a,const U &b){return a>b?a=b,1:0;}
template <class T> void psum(T& c) {partial_sum(begin(c), end(c), begin(c));}
template<class T> using heap=priority_queue<T,vector<T>,greater<T>>;
struct before_main_function {
before_main_function() {
cin.tie(nullptr); ios::sync_with_stdio(0);
cout << setprecision(15) << fixed;
// #define endl "\n"
}
} before_main_function;
//------------------8<------------------------------------8<--------------------
struct union_find {
vector<int> data;
int comp;
union_find(int size) : data(size, -1), comp(size) {}
void unite(int x, int y) {
x = root(x); y = root(y);
if(x != y) {
if(data[y] < data[x]) swap(x, y);
data[x] += data[y];
data[y] = x;
comp--;
}
}
bool same(int x, int y) {
return root(x) == root(y);
}
int root(int x) {
return data[x] < 0 ? x : (data[x] = root(data[x]));
}
int size(int x) {
return -data[root(x)];
}
int components() { return comp; }
};
struct LCA {
using Query = pii;
const vvi &g;
vi color;
vi ancestor;
vector<vector<pair<int, Query>>> query_set;
union_find uf;
vi res;
vi dist;
LCA(const vvi &g, vector<Query> &query) :
g (g),
color (sz(g)),
ancestor (sz(g)),
query_set (sz(g)),
uf (sz(g)),
res (sz(query)),
dist (sz(g))
{
int qs = sz(query);
rep(i, 0, qs) {
query_set[query[i].first ].emplace_back(i, query[i]);
query_set[query[i].second].emplace_back(i, query[i]);
}
}
void visit(int v, int prev, int d) {
ancestor[uf.root(v)] = v;
for (auto &w : g[v]) {
if (w == prev) {
continue;
}
visit(w, v, d + 1);
uf.unite(v, w);
ancestor[uf.root(v)] = v;
}
dist[v] = d;
color[v] = 1;
for (auto &p : query_set[v]) {
Query q = p.second;
int w = (q.second == v ? q.first
: (q.first == v ? q.second : -1));
if (w == -1 || !color[w]) {
continue;
}
res[p.first] = ancestor[uf.root(w)];
}
}
vi solve(int root) {
visit(root, -1, 0);
return res;
}
};
signed main() {
int N, M, Q;
cin >> N >> M >> Q;
vector<vector<int>> G(N);
vector<int> num(N);
rep(i, 0, M) {
int a, b;
cin >> a >> b;
a--, b--;
G[a].push_back(b);
G[b].push_back(a);
}
vector<int> comp(N, -1);
vector<int> roots;
rep(i, 0, N) {
if (comp[i] != -1) continue;
static int comp_id = 0;
roots.push_back(i);
comp_id++;
comp[i] = comp_id;
auto dfs = [&](auto fun, int v) -> void {
comp[v] = comp_id;
for (int w : G[v]) {
if (comp[w] != -1) continue;
fun(fun, w);
}
};
dfs(dfs, i);
}
int ans = 0;
vector<pii> lca_query;
rep(i, 0, Q) {
int a, b;
cin >> a >> b;
a--, b--;
if (comp[a] == comp[b]) {
lca_query.push_back({a, b});
} else {
num[a]++;
num[b]++;
}
}
vector<pii> dp(N, pii(0, 0));
for (int root : roots) {
auto dfs1 = [&](auto fun, int v, int p) -> void {
pii cnt_dist = {num[v], 0};
for (int w : G[v]) {
if (w == p) continue;
fun(fun, w, v);
cnt_dist.first += dp[w].first;
cnt_dist.second += dp[w].second + dp[w].first;
}
dp[v] = cnt_dist;
};
dfs1(dfs1, root, -1);
auto dfs2 = [&](auto fun, int v, int p, pii upper) -> int {
int ret = INF;
int tmp = dp[v].second + upper.second;
for (int w : G[v]) {
if (w == p) continue;
int c = dp[v].first - dp[w].first + upper.first;
int d = dp[v].second - (dp[w].second + dp[w].first) + c + upper.second;
chmin(ret, fun(fun, w, v, {c, d}));
}
chmin(ret, tmp);
return ret;
};
int mn = dfs2(dfs2, root, -1, {0, 0});
ans += mn;
}
{
LCA lca(G, lca_query);
for (int r : roots) {
lca.solve(r);
}
rep(i, 0, sz(lca_query)) {
int a = lca_query[i].first;
int b = lca_query[i].second;
int l = lca.res[i];
ans += lca.dist[a] + lca.dist[b] - 2 * lca.dist[l];
}
}
cout << ans << endl;
return (0^_^0);
}
algon_320