Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <cstdio>
- #include <vector>
- #include <cmath>
- #include <algorithm>
- #include <cstring>
- #define task ""
- using namespace std;
- using ll = int;
- using ld = long double;
- const int N = 5e2 + 2;
- const ll Inf = 1e9;
- int x[N], y[N], node[N][N], lab[N * N], ranks[N * N];
- bool chosen[N][N];
- ll d[N * N], maxn[N * N][19];
- pair<int, int> a[N * N];
- int n, m, l(0), par[N * N][19], q;
- vector<int> exist, adj[N * N], ck[N];
- #define sqr(x) ((x) * (x))
- ll dis(int i, int j)
- {
- return sqr(x[i] - x[j]) + sqr(y[i] - y[j]);
- }
- void Read()
- {
- cin >> n;
- for (int i = 1; i <= n; ++i)
- cin >> x[i] >> y[i];
- for (int i = 1; i <= n; ++i)
- for (int j = 1; j <= n; ++j)
- node[i][j] = ++l,
- a[l] = {i, j},
- d[l] = dis(i, j),
- exist.push_back(l);
- cin >> m;
- for (int i = 1; i <= m; ++i)
- {
- int u, v;
- cin >> u >> v;
- ck[u].push_back(v);
- ck[v].push_back(u);
- }
- //cerr << "\n";
- }
- int findpar(int v)
- {
- return lab[v] < 0 ? v : lab[v] = findpar(lab[v]);
- }
- void Union(int u, int v)
- {
- lab[u] += lab[v];
- lab[v] = u;
- }
- void dfs(int v)
- {
- for (int i = 1; i <= log2(ranks[v]); ++i)
- par[v][i] = par[par[v][i - 1]][i - 1],
- maxn[v][i] = min(maxn[v][i - 1], maxn[par[v][i - 1]][i - 1]);
- for (auto i : adj[v])
- if (!ranks[i])
- {
- par[i][0] = v;
- maxn[i][0] = d[v];
- ranks[i] = ranks[v] + 1;
- dfs(i);
- }
- }
- void Make_tree()
- {
- memset(lab, -1, sizeof lab);
- fill_n(&maxn[0][0], 19 * N * N, Inf);
- sort(exist.begin(), exist.end(), [&](int &x, int &y) { return d[x] > d[y]; });
- //cerr << "Sort ok\n";
- for (auto i : exist)
- {
- int x = a[i].first,
- y = a[i].second,
- u = findpar(i);
- for (auto j : ck[x])
- {
- if (chosen[j][y])
- {
- int v = findpar(node[j][y]);
- if (u != v)
- {
- adj[node[j][y]].push_back(i);
- adj[i].push_back(node[j][y]);
- Union(u, v);
- }
- }
- }
- for (auto j : ck[y])
- {
- if (chosen[x][j])
- {
- int v = findpar(node[x][j]);
- if (u != v)
- {
- adj[node[x][j]].push_back(i);
- adj[i].push_back(node[x][j]);
- Union(u, v);
- }
- }
- }
- chosen[x][y] = 1;
- }
- //cerr << "Edge ok\n";
- for (int i = 1; i <= n * n; ++i)
- if (!ranks[i])
- {
- ranks[i] = 1;
- dfs(i);
- }
- }
- ll LCA(int u, int v)
- {
- if (ranks[u] < ranks[v])
- swap(u, v);
- ll ans = min(d[u], d[v]);
- for (int i = log2(ranks[u]); ~i; --i)
- if (ranks[par[u][i]] >= ranks[v])
- {
- ans = min(ans, maxn[u][i]);
- u = par[u][i];
- }
- for (int i = log2(ranks[u]); ~i; --i)
- if (par[u][i] != par[v][i])
- {
- ans = min(ans, min(maxn[u][i], maxn[v][i]));
- u = par[u][i];
- v = par[v][i];
- }
- while (u != v)
- {
- ans = min(ans, min(maxn[u][0], maxn[v][0]));
- u = par[u][0];
- v = par[v][0];
- }
- return ans;
- }
- void Solve()
- {
- int a, b;
- cin >> a >> b;
- int u = node[a][b],
- v = node[b][a];
- cout << LCA(u, v) << "\n";
- }
- int32_t main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- if (fopen(task ".INP", "r"))
- freopen(task ".INP", "r", stdin),
- freopen(task ".OUT", "w", stdout);
- Read();
- //cerr << "Read ok\n";
- Make_tree();
- //cerr << "Make_tree ok\n";
- for (cin >> q; q--;)
- Solve();
- }
- /*
- 6
- 0 0
- -1 3
- -1 0
- -1 -3
- 3 0
- 0 1
- 6
- 1 2
- 2 3
- 3 4
- 4 1
- 1 5
- 5 6
- 5
- 6 5
- 2 4
- 2 6
- 3 6
- 4 6
- */
Advertisement
Add Comment
Please, Sign In to add comment