1 条题解
-
0
题意就是算非树边覆盖的树边有交的对数。
可以枚举一条边,树上差分求出它被几条非树边覆盖,设为 ,则这条边带来了 的答案。可惜这样会算重。
注意到问题在于,两条链的交是一条链,这条链上的所有边都会算一次,但一共只该被算一次。
用改进的点 - 边容斥,算 边的答案 - 两条边的答案即可。两条边的答案除了 LCA 那里都可以树上差分,LCA 处可以用个 map 统计。
#include <bits/stdc++.h> using namespace std; typedef pair<int, int> pr; int n, m, cnt, h[200005], p[200005][20], d[200005], c2[200005], c1[200005]; long long ans = 0; map<pr, int> mp; struct Edge { int to, next; } e[400005]; void Add_Edge(int x, int y) { e[++cnt].to = y; e[cnt].next = h[x]; h[x] = cnt; } void DFS(int x, int fa) { p[x][0] = fa, d[x] = d[fa] + 1; for (int i = h[x]; i; i = e[i].next) { int y = e[i].to; if (y == fa) continue; DFS(y, x); } } void MakeST() { for (int j = 1; j <= 18; j++) { for (int i = 1; i <= n; i++) p[i][j] = p[p[i][j - 1]][j - 1]; } } int LCA(int x, int y) { if (d[x] < d[y]) swap(x, y); for (int i = 18; i >= 0; i--) if (d[p[x][i]] >= d[y]) x = p[x][i]; if (x == y) return x; for (int i = 18; i >= 0; i--) if (p[x][i] ^ p[y][i]) x = p[x][i], y = p[y][i]; return p[x][0]; } int Getson(int x, int lca) { if (x == lca) return 0; for (int i = 18; i >= 0; i--) if (d[p[x][i]] > d[lca]) x = p[x][i]; return x; } void DFS2(int x) { for (int i = h[x]; i; i = e[i].next) { int y = e[i].to; if (y != p[x][0]) DFS2(y), c1[x] += c1[y], c2[x] += c2[y]; } ans -= 1ll * c1[x] * (c1[x] - 1) / 2; ans += 1ll * c2[x] * (c2[x] - 1) / 2; // cout << x << ' ' << c1[x] << ' ' << c2[x] << '\n'; } int main() { scanf("%d%d", &n, &m); for (int i = 1, x, y; i < n; i++) scanf("%d%d", &x, &y), Add_Edge(x, y), Add_Edge(y, x); DFS(1, 0); MakeST(); for (int i = 1, x, y; i <= m - n + 1; i++) { scanf("%d%d", &x, &y); int lca = LCA(x, y); // c1[x]++, c1[y]++; // c1[lca]--; // c1[p[lca][0]]--; c2[x]++, c2[y]++; c2[lca] -= 2; if (x != lca && y != lca) { c1[x]++; c1[y]++; int u = Getson(x, lca), v = Getson(y, lca); c1[u]--; c1[v]--; if (u > v) swap(u, v); mp[pr(u, v)]++; } else { if (d[x] > d[y]) swap(x, y); if (p[y][0] == x) continue; c1[y]++; c1[Getson(y, lca)]--; } } DFS2(1); for (auto [x, y] : mp) ans -= 1ll * y * (y - 1) / 2; printf("%lld\n", ans); }
- 1
信息
- ID
- 6773
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 13
- 已通过
- 6
- 上传者