#include using namespace std; using int64 = long long; using i64 = int64; #define rep(i,N) for(int i=0;i<(int)(N); ++i) const int inf = 1 << 30; const int64 inf64 = 1ll << 60; template< typename G > struct DoublingLowestCommonAncestor { const int LOG; vector< int > dep; const G &g; vector< vector< int > > table; DoublingLowestCommonAncestor(const G &g) : g(g), dep(g.size()), LOG(32 - __builtin_clz(g.size())) { table.assign(LOG, vector< int >(g.size(), -1)); } void dfs(int idx, int par, int d) { table[0][idx] = par; dep[idx] = d; for(auto &to : g[idx]) { if(to != par) dfs(to, idx, d + 1); } } void build() { dfs(0, -1, 0); for(int k = 0; k + 1 < LOG; k++) { for(int i = 0; i < table[k].size(); i++) { if(table[k][i] == -1) table[k + 1][i] = -1; else table[k + 1][i] = table[k][table[k][i]]; } } } pair query(int u, int v) { if(dep[u] > dep[v]) swap(u, v); int iu = u, iv = v; for(int i = LOG - 1; i >= 0; --i) { if(((dep[v] - dep[u]) >> i) & 1) v = table[i][v]; } if(u == v) { return make_pair(u, dep[iv] - dep[iu]); } iu = u, iv = v; for(int i = LOG - 1; i >= 0; --i) { if(table[i][u] != table[i][v]) { u = table[i][u]; v = table[i][v]; } } return make_pair(table[0][u], dep[iu] + dep[iv] - 2 * dep[table[0][u]]); } }; int main() { using P = pair; int N, M, Q; cin >> N >> M >> Q; vector> G(N); rep(i, M) { int u, v; cin >> u >> v, u--, v--; G[u].emplace_back(v); G[v].emplace_back(u); } vector a(Q), b(Q); rep(i, Q) cin >> a[i] >> b[i], a[i]--, b[i]--; vector>>> lcas; vector idx(N, -1); int v = 0; vector convert(N); vector>> gs; rep(i, N) { if(idx[i] != -1) continue; idx[i] = v++; stack stk; stk.emplace(i); convert[i] = 0; vector> g; g.emplace_back(vector()); int num = 0; while(!stk.empty()) { int i = stk.top(); stk.pop(); for(auto &e : G[i]) { if(idx[e] != -1) continue; idx[e] = idx[i]; stk.emplace(e); convert[e] = ++num; g.emplace_back(vector()); g[convert[i]].emplace_back(convert[e]); g[convert[e]].emplace_back(convert[i]); } } lcas.emplace_back(DoublingLowestCommonAncestor>>(g)); gs.emplace_back(g); lcas.back().build(); } /* rep(i, N) cout << idx[i] << " "; cout << endl; rep(i, N) cout << convert[i] << " "; cout << endl; */ vector w(N); i64 ans = 0; rep(i, Q) { if(idx[a[i]] == idx[b[i]]) { P p = lcas[idx[a[i]]].query(convert[a[i]], convert[b[i]]); //cout << a[i] << " " << b[i] << endl; //cout << convert[a[i]] << " " << convert[b[i]] << endl; //cout << p.first << endl; ans += p.second; } else { w[a[i]]++; w[b[i]]++; } } vector

root(lcas.size(), P(-1, -1)); rep(i, N) { if(root[idx[i]].second < w[i]) { root[idx[i]] = P(convert[i], w[i]); } } vector> d(gs.size()); rep(i, gs.size()) { d[i].assign(gs[i].size(), inf); stack stk; stk.emplace(root[i].first); d[i][root[i].first] = 0; while(!stk.empty()) { int idx = stk.top(); stk.pop(); for(auto &e : gs[i][idx]) { if(d[i][e] <= d[i][idx] + 1) continue; d[i][e] = d[i][idx] + 1; stk.emplace(e); } } } rep(i, N) { if(idx[a[i]] == idx[b[i]]) continue; if(w[i] == 0) continue; ans += d[idx[a[i]]][convert[a[i]]] * w[a[i]]; ans += d[idx[b[i]]][convert[b[i]]] * w[b[i]]; } cout << ans << endl; }