1 条题解
-
0
缩点建新图
#include <bits/stdc++.h> using namespace std; const int MAXN = 200000; // 原图 int n; vector<int> ee[MAXN + 5]; // 所属王国 int id[MAXN + 5]; queue<int> q; // 标王国用到的队列 // 同王国的点缩成一个点后的新图 vector<int> e[MAXN + 5]; // -------start LCA-------- // f[i][j] 记录 i 的 2^j 级别祖先 int f[MAXN + 5][25]; // dep[i] 求节点 i 的深度 int dep[MAXN + 5]; void dfs(int u, int fa) { f[u][0] = fa; for (int i = 0; i < e[u].size(); i++) { int v = e[u][i]; if (v == fa) continue; dep[v] = dep[u] + 1; dfs(v, u); } } void init(int s) { dep[s] = 0; dfs(s, 0); // 预处理深度 dep[u],以及一级祖先 f[u][0] // i 的 2^j 级别祖先 = i 的 2^{j-1} 级别祖先的 2^{j-1} 级别祖先 for (int j = 1; (1LL << j) <= n; j++) for (int i = 1; i <= n; i++) f[i][j] = f[f[i][j - 1]][j - 1]; } // lca(u,v) 返回 u,v 的最近公共祖先 int lca(int u, int v) { // 保证 u 在上面,v 在下面 if (dep[v] < dep[u]) swap(u, v); // 拉到同样的深度 for (int j = 20; j >= 0; j--) if (dep[v] - dep[u] >= (1 << j)) v = f[v][j]; // 初始两点之间是祖孙关系时,拉到同样深度就会变成同一个点 if (u == v) return u; // 同步往上走,跳到了 lca 下面一跳位 for (int j = 20; j >= 0; j--) if (f[u][j] != f[v][j]) u = f[u][j], v = f[v][j]; return f[u][0]; } // -------end LCA-------- int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n; for (int i = 1; i <= n - 1; i++) { int u, v; cin >> u >> v; ee[u].push_back(v); ee[v].push_back(u); } // 标所属王国 for (int i = 1; i <= n; i++) if (ee[i].size() > 2) { id[i] = i; q.push(i); } while (!q.empty()) { int u = q.front(); q.pop(); for (int v : ee[u]) if (!id[v]) { id[v] = id[u]; q.push(v); } } // 建立新图 for (int u = 1; u <= n; u++) for (int v : ee[u]) if (id[u] != id[v]) e[id[u]].push_back(id[v]); // LCA 初始化 int root = id[1]; // 1 号点所属王国首都记为根节点 init(id[1]); // Q 次询问 int Q; cin >> Q; while (Q--) { int u, v; cin >> u >> v; u = id[u]; v = id[v]; int uv = lca(u, v); cout << dep[u] + dep[v] - 2 * dep[uv] + 1 << "\n"; } return 0; }
不缩点直接做
#include<bits/stdc++.h> using namespace std; int n,Q; int x,y; int dist[200005],vis[200005],sum[200005],f[200005][25]; queue<int> M; vector<int> G[200005]; void dfs(int x,int fa){ dist[x]=dist[fa]+1; f[x][0]=fa; sum[x]=sum[fa]; if (vis[fa]!=vis[x]) sum[x]++; int siz=(int)G[x].size(); for (int i=0;i<=siz-1;i++){ if (fa==G[x][i]) continue; dfs(G[x][i],x); } } int lca(int x,int y){ if (dist[x]>dist[y]) swap(x,y); for (int i=20;i>=0;i--){ if (dist[x]+(1LL<<i)<=dist[y]) y=f[y][i]; } if (x==y) return x; for (int i=20;i>=0;i--){ if (f[x][i]!=f[y][i]){ x=f[x][i]; y=f[y][i]; } } return f[x][0]; } int main(){ cin>>n; for (int i=1;i<=n-1;i++){ cin>>x>>y; G[x].push_back(y); G[y].push_back(x); } for (int i=1;i<=n;i++){ if (G[i].size()>=3){ M.push(i); vis[i]=i; } } while (M.size()>0){ int now=M.front();M.pop(); int siz=G[now].size(); for (int i=0;i<siz;i++){ int nxt=G[now][i]; if (vis[nxt]==0){ vis[nxt]=vis[now]; M.push(nxt); } } } dfs(1,0); for (int k=1;k<=20;k++){ for (int i=1;i<=n;i++){ f[i][k]=f[f[i][k-1]][k-1]; } } cin>>Q; while (Q--){ cin>>x>>y; int xy=lca(x,y); int ans=sum[x]+sum[y]-sum[xy]-sum[f[xy][0]]; if (vis[xy]==vis[f[xy][0]]) ans++; cout<<ans<<'\n'; } }
- 1
信息
- ID
- 13423
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- 8
- 标签
- 递交数
- 16
- 已通过
- 5
- 上传者