結果
| 問題 |
No.922 東北きりきざむたん
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2019-11-08 22:17:02 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 3,214 bytes |
| コンパイル時間 | 2,348 ms |
| コンパイル使用メモリ | 190,312 KB |
| 実行使用メモリ | 32,904 KB |
| 最終ジャッジ日時 | 2024-09-15 01:34:33 |
| 合計ジャッジ時間 | 6,712 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 8 WA * 4 TLE * 1 -- * 13 |
ソースコード
#include <bits/stdc++.h>
#define rep(i,n)for(int i=0;i<(n);i++)
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const ll INF=0x3f3f3f3f3f3f3f3f;
class UnionFind {
vector<int>par, sz;
public:
UnionFind() {}
UnionFind(int n) {
par = sz = vector<int>(n);
for (int i = 0; i < n; i++) {
par[i] = i;
sz[i] = 1;
}
}
int find(int x) {
if (par[x] == x)return x;
return par[x] = find(par[x]);
}
void unite(int x, int y) {
x = find(x); y = find(y);
if (x == y)return;
if (sz[x] > sz[y]) {
par[y] = x;
sz[x] += sz[y];
}
else {
par[x] = y;
sz[y] += sz[x];
}
}
bool same(int x, int y) {
return find(x) == find(y);
}
int size(int x) {
return sz[find(x)];
}
};
class LCA{
public:
vector<vector<pair<int,int>>>E;
vector<vector<int>>par;
vector<int>d1;
vector<long long>d2;
vector<bool>used;
int MAX_LOG=22;
int n;
LCA(){}
LCA(int N){
n=N;
E=vector<vector<pair<int,int>>>(n);
par=vector<vector<int>>(MAX_LOG,vector<int>(n));
d1=vector<int>(n);
d2=vector<long long>(n);
used=vector<bool>(n);
}
void add_edge(int a,int b,int c){
E[a].push_back(make_pair(c,b));
E[b].push_back(make_pair(c,a));
}
void add_edge(int a,int b){
E[a].push_back(make_pair(1,b));
E[b].push_back(make_pair(1,a));
}
private:
void dfs(int u,int p,int a,long long b){
used[u]=true;
par[0][u]=p;d1[u]=a;d2[u]=b;
for(auto&v:E[u]){
if(v.second!=p)dfs(v.second,u,a+1,b+v.first);
}
}
bool flag=false;
void init(){
for(int i=0;i<n;i++){
if(!used[i])dfs(0,-1,0,0);
}
for(int i=1;i<MAX_LOG;i++)for(int j=0;j<n;j++){
if(par[i-1][j]==-1)par[i][j]=-1;
else par[i][j]=par[i-1][par[i-1][j]];
}
flag=true;
}
public:
int lca(int u,int v){
if(!flag)init();
if(d1[u]>d1[v])swap(u,v);
for(int i=0;i<MAX_LOG;i++){
if((d1[v]-d1[u])>>i&1)v=par[i][v];
}
if(u==v)return u;
for(int i=MAX_LOG-1;i>=0;i--){
if(par[i][u]!=par[i][v]){
u=par[i][u];
v=par[i][v];
}
}
return par[0][u];
}
long long dist(int u,int v){
int l=lca(u,v);
return d2[u]+d2[v]-d2[l]*2;
}
};
vector<int>E[200000];
ll dp[200000];
ll sum[200000];
int sz[200000];
bool used[200000];
int all[200000];
UnionFind uf;
void dfs(int v,int p){
used[v]=true;
for(int u:E[v]){
if(u==p)continue;
dfs(u,v);
sum[v]+=sum[u]+sz[u];
sz[v]+=sz[u];
}
}
void dfs2(int v,int p){
used[v]=true;
if(p==-1){
dp[v]=sum[v];
}
else{
dp[v]=(dp[p]-(sum[v]+sz[v]))+(all[uf.find(v)]-sz[v])+sum[v];
}
for(int u:E[v]){
if(u!=p)dfs2(u,v);
}
}
ll Min[200000];
int main(){
int n,m,q;cin>>n>>m>>q;
uf=UnionFind(n);
LCA lca(n);
rep(i,m){
int a,b;scanf("%d%d",&a,&b);a--;b--;
E[a].push_back(b);
E[b].push_back(a);
lca.add_edge(a,b);
uf.unite(a,b);
}
ll ans=0;
rep(i,q){
int a,b;scanf("%d%d",&a,&b);a--;b--;
if(uf.same(a,b)){
ans+=lca.dist(a,b);
}
else{
sz[a]++;
sz[b]++;
}
}
rep(i,n){
all[uf.find(i)]+=sz[i];
}
memset(used,0,sizeof(used));
rep(i,n){
if(!used[i])dfs(i,-1);
}
memset(used,0,sizeof(used));
rep(i,n){
if(!used[i])dfs2(i,-1);
}
memset(Min,0x3f,sizeof(Min));
rep(i,n){
int p=uf.find(i);
Min[p]=min(Min[p],dp[i]);
}
rep(i,n){
if(Min[i]!=INF)ans+=Min[i];
}
cout<<ans<<endl;
}