Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <cstdio>
- #include <cmath>
- #define task "CNET"
- using namespace std;
- using ll = long long;
- using ld = long double;
- const int N = 1e5 + 2;
- int n, m, ranks[N], par[N][18], Blue[N], Gay[N];
- vector<pair<int, int>> adj[N];
- bool blue[N * 2], gay[N * 2], multi[N * 2];
- pair<int, int> s[N * 2];
- int num[N], low[N], cnt(0);
- void Read()
- {
- cin >> n >> m;
- for (int i = 1; i <= m; ++i)
- {
- cin >> s[i].first >> s[i].second;
- if (s[i].first > s[i].second)
- swap(s[i].first, s[i].second);
- }
- sort(s + 1, s + m + 1);
- for (int i = 1; i <= m; ++i)
- {
- int j = i;
- while (j <= m && s[i] == s[j])
- ++j;
- adj[s[i].first].emplace_back(s[i].second, i);
- adj[s[i].second].emplace_back(s[i].first, i);
- multi[i] = j - i > 1;
- i = j - 1;
- }
- }
- void dfs(int v, int p = 1)
- {
- int child(0);
- num[v] = low[v] = ++cnt;
- for (auto t : adj[v])
- if (t.first != p)
- {
- int &i = t.first;
- if (num[i])
- low[v] = min(low[v], num[i]);
- else
- {
- par[i][0] = v;
- ++child;
- dfs(i, v);
- /// CriticalEdge
- if (low[i] > num[v] && !multi[t.second])
- blue[t.second] = 1;
- /// CriticalNode
- if (v != p && low[i] >= num[v])
- gay[t.second] = 1;
- low[v] = min(low[v], low[i]);
- }
- }
- if (v == p)
- if (child > 1)
- for (auto t : adj[v])
- if (par[t.first][0] == v)
- if (low[t.first] >= num[v])
- gay[t.second] = 1;
- }
- void GetAns(int v)
- {
- for (int i = 1; i <= 17; ++i)
- par[v][i] = par[par[v][i - 1]][i - 1];
- for (auto t : adj[v])
- if (par[t.first][0] == v)
- {
- int &i = t.first;
- ranks[i] = ranks[v] + 1;
- Blue[i] = Blue[v] + blue[t.second];
- Gay[i] = Gay[v] + gay[t.second];
- GetAns(t.first);
- }
- }
- int lca(int u, int v)
- {
- if (ranks[u] < ranks[v])
- swap(u, v);
- for (int i = log2(ranks[u]); ~i; --i)
- if (ranks[par[u][i]] >= ranks[v])
- u = par[u][i];
- for (int i = log2(ranks[u]); ~i; --i)
- if (par[u][i] != par[v][i])
- {
- u = par[u][i];
- v = par[v][i];
- }
- while (u != v)
- {
- u = par[u][0];
- v = par[v][0];
- }
- return v;
- }
- int Check(int u, int v, int t)
- {
- if (u == t || v == t)
- {
- if (u == t)
- swap(u, v);
- for (int i = log2(ranks[u]); ~i; --i)
- if (ranks[par[u][i]] > ranks[t])
- u = par[u][i];
- return Gay[u] - Gay[t];
- }
- else
- {
- for (int i = log2(ranks[u]); ~i; --i)
- if (ranks[par[u][i]] > ranks[t])
- u = par[u][i];
- for (int i = log2(ranks[v]); ~i; --i)
- if (ranks[par[v][i]] > ranks[t])
- v = par[v][i];
- return (Gay[u] - Gay[t]) && (Gay[v] - Gay[t]);
- }
- }
- void Solve()
- {
- int q;
- cin >> q;
- while (q--)
- {
- int a, b;
- cin >> a >> b;
- int v = lca(a, b);
- cout << Gay[a] + Gay[b] - 2 * Gay[v] + 2 - Check(a, b, v) << " ";
- cout << Blue[a] + Blue[b] - 2 * Blue[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();
- dfs(1);
- ranks[1] = 1;
- GetAns(1);
- Solve();
- }
Advertisement
Add Comment
Please, Sign In to add comment