列表

详情


NC24217. [USACO 2019 Jan P]Exercise Route

描述

奶牛Bessie意识到为了保持好的体形她需要更多地进行锻炼。她需要你帮助她选择在农场里每天用来晨跑的路线。

农场由N块草地组成(1≤N≤2⋅10^5),方便起见编号为1…N,由M条双向的小路连接(1≤M≤2⋅10^5)。作为一种遵循规律的生物,奶牛们倾向于使用其中特定的N−1条小路作为她们日常在草地之间移动的路线——她们管这些叫“常规的”小路。从每块草地出发都可以仅通过常规的小路到达所有其他草地。

为了使她的晨跑更加有趣,Bessie觉得她应该选择一条包含一些非常规的小路的路线。然而,使用常规的小路能够使她感到舒适,所以她不是很想在她的路线中使用过多非常规的小路。经过一些思考,她认为一条好的路线应当形成一个简单环(能够不经过任何草地超过一次的情况下回到起点),其中包含恰好两条非常规的小路。

请帮助Bessie计算她可以使用的好的路线的数量。两条路线被认为是相同的,如果它们包含的小路的集合相等。

输入描述

输入的第一行包含N和M。以下M行每行包含两个整数ai和bi,描述了一条小路的两端。其中前N−1条是常规的小路。

输出描述

输出Bessie可以选择的路线的总数。

示例1

输入:

5 8
1 2
1 3
1 4
1 5
2 3
3 4
4 5
5 2

输出:

4

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 335ms, 内存消耗: 22576K, 提交时间: 2022-04-06 10:40:33

// USACO 2019 Jan P. Exercise Route
#include <bits/stdc++.h>
const int NN = 2e5 + 4;
using namespace std;
using VI = vector<int>;
VI G[NN];
int fa[NN][20], D[NN], Sum[NN], Sz[NN], HH;
void dfs(int u, int f, int d) {
  fa[u][0] = f, D[u] = d;
  for (int i = 1; (1 << i) <= d; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1];
  for (int v : G[u])
    if (v != f) dfs(v, u, d + 1);
}
int lca(int u, int v) {
  if (D[u] < D[v]) swap(u, v);
  for (int i = HH; i >= 0; i--)
    if ((1 << i) & (D[u] - D[v]))
      // D[fa[u][i]] >= D[v])
      u = fa[u][i];
  if (u == v) return u;
  for (int i = HH; i >= 0; i--)
    if (fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
  return fa[u][0];
}
int topBelow(int u, int anc) {
  if (u == anc) return 0;
  for (int i = HH; i >= 0; i--)
    if (D[fa[u][i]] > D[anc]) u = fa[u][i];
  return u;
}
void dfs2(int u, int f, int s) {
  Sz[u] = s;
  for (int v : G[u])
    if (v != f) dfs2(v, u, s + Sum[v]);
}
int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  int n, m;
  cin >> n >> m, HH = ceil(log2(n)) + 1;
  for (int i = 1, x, y; i <= n - 1; i++)
    cin >> x >> y, G[x].push_back(y), G[y].push_back(x);
  dfs(1, 0, 1);
  long long ans = 0;
  VI A(m + 1), B(m + 1);
  map<pair<int, int>, int> Q;
  for (int i = n; i <= m; i++) {
    cin >> A[i] >> B[i];
    int d = lca(A[i], B[i]), ta = topBelow(A[i], d), tb = topBelow(B[i], d);
    if (ta) ans -= ++Sum[ta];
    if (tb) ans -= ++Sum[tb];
    if (ta && tb) {
      if (ta > tb) swap(ta, tb);
      ans -= Q[{ta, tb}]++;
    }
  }
  dfs2(1, 1, 0);
  for (int i = n; i <= m; i++)
    ans += Sz[A[i]] + Sz[B[i]] - 2 * Sz[lca(A[i], B[i])];
  cout << ans << "\n";
  return 0;
}

上一题