結果
| 問題 |
No.922 東北きりきざむたん
|
| コンテスト | |
| ユーザー |
koi_kotya
|
| 提出日時 | 2019-11-08 22:56:50 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 3,702 bytes |
| コンパイル時間 | 1,950 ms |
| コンパイル使用メモリ | 180,448 KB |
| 実行使用メモリ | 68,128 KB |
| 最終ジャッジ日時 | 2024-09-15 02:04:39 |
| 合計ジャッジ時間 | 15,696 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 3 TLE * 3 -- * 20 |
ソースコード
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
int const INF = 1<<30;
#define p_ary(ary,a,b) do { cout << "["; for (int count = (a);count < (b);++count) cout << ary[count] << ((b)-1 == count ? "" : ", "); cout << "]\n"; } while(0)
#define p_map(map,it) do {cout << "{";for (auto (it) = map.begin();;++(it)) {if ((it) == map.end()) {cout << "}\n";break;}else cout << "" << (it)->first << "=>" << (it)->second << ", ";}}while(0)
int MAX_N = 100010;
vector<int> depth(MAX_N,0),dist(MAX_N,0);
vector<vector<int>> edges(MAX_N),anc(MAX_N);
vector<int> cnt(MAX_N,0);
vector<bool> used(MAX_N,false);
vector<int> child_sum(MAX_N,0);
void dfs(int i,int p = -1) {
for (int j : edges[i]) if (j != p) {
anc[j].push_back(i);
depth[j] = depth[i]+1;
dist[j] = dist[i]+1;
dfs(j,i);
}
}
void init(int k) {
depth[k] = 0;
dist[k] = 0;
dfs(k);
int n = anc.size();
for (int i = 0;i < 20;++i) {
for (int j = 0;j < n;++j) {
if (anc[j].size() < i+1 || anc[anc[j][i]].size() < i+1) continue;
anc[j].push_back(anc[anc[j][i]][i]);
}
}
}
int lca(int i,int j) {
if (depth[i] > depth[j]) swap(i,j);
while (depth[i] < depth[j]) {
for (int k = anc[j].size()-1;k >= 0;--k) if (depth[anc[j][k]] >= depth[i]) {
j = anc[j][k];
break;
}
}
while (i != j) {
for (int k = anc[i].size()-1;k >= 0;--k) {
if (anc[i][k] != anc[j][k]) {
i = anc[i][k];
j = anc[j][k];
break;
} else if (k == 0) {
i = j = anc[i][0];
}
}
}
return i;
}
int calc_dist(int i,int j) {
return dist[i]+dist[j]-dist[lca(i,j)]*2;
}
struct UnionFind {
private:
vector<int> par,depth;
public:
UnionFind (int n) {
par.resize(n);
depth = vector<int>(n,0);
for (int i = 0;i < n;++i) par[i] = i;
}
int find(int x) {
if (par[x] == x) return x;
else return par[x] = find(par[x]);
}
void unite(int x,int y) {
x = find(x);
y = find(y);
if (x == y) return;
if (depth[x] < depth[y]) par[x] = y;
else {
par[y] = x;
if (depth[x] == depth[y]) depth[x]++;
}
}
bool same(int x,int y) {
return find(x) == find(y);
}
};
void dfs1(ll& s,int i,int p = -1) {
child_sum[i] = cnt[i];
s += cnt[i]*dist[i];
for (int& j : edges[i]) if (j != p) {
dfs1(s,j,i);
child_sum[i] += child_sum[j];
}
}
void dfs2(ll& sum,ll& mn,ll po,int i,int p = -1) {
used[i] = true;
mn = min(mn,sum);
for (int& j : edges[i]) if (j != p) {
sum += po-2*child_sum[j];
dfs2(sum,mn,po,j,i);
sum -= po-2*child_sum[j];
}
}
int main() {
int n,m,q;
cin >> n >> m >> q;
UnionFind uf(n);
vector<P> qry(q);
for (int i = 0;i < m;++i) {
int u,v;
cin >> u >> v;
u--;v--;
edges[u].push_back(v);
edges[v].push_back(u);
uf.unite(u,v);
}
for (int i = 0;i < q;++i) cin >> qry[i].first >> qry[i].second;
ll ans = 0;
for (int i = 0;i < n;++i) if (dist[i] == 0) init(i);
for (P& p : qry) {
int i = p.first-1,j = p.second-1;
if (uf.same(i,j)) ans += calc_dist(i,j);
else {
cnt[i]++;
cnt[j]++;
}
}
for (int i = 0;i < n;++i) if (!used[i]) {
ll sum = 0;
dfs1(sum,i);
ll mn = sum;
ll po = child_sum[i];
dfs2(sum,mn,po,i);
ans += mn;
}
cout << ans << endl;
return 0;
}
koi_kotya