Description

题目链接
给顶一个n个顶点、n条边的图,统计图内简单路径的数量。

Solution

数据很有特点, 个顶点并且具有 条边。如果是 条边的话显然是一棵树。
树上简单路径如何计算呢? 假设当前树的节点有 个,显然是
现在多了一条边,可以看成是多棵树相互独立,中间是一个环,如下图:
图片说明
由红圈中三个子树构成,分别拥有节点个数为3、3、3
对于每个子树我们统计节点数 ,可以计算贡献
那么剩下的就是如何统计节点了,类似于拓扑排序,每次把度为1的点都放到队列里,慢慢删边即可。
时间复杂度

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
set<int> G[N];
ll vis[N];
int main() {
  ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
  int T; cin >> T;
  while(T--) {
    int n; cin >> n;
    for(int i = 1; i <= n; i++) G[i].clear(), vis[i] = 1;
    for(int i = 1; i <= n; i++) {
      int u, v; cin >> u >> v;
      G[u].insert(v);
      G[v].insert(u);
    }
    queue<int> q;
    for(int i = 1; i <= n; i++) {
      if(G[i].size() == 1) {
        q.push(i);
        vis[i] = 1;
      }
    }
    while(!q.empty()) {
      int u = q.front(); q.pop();
      for(auto &v : G[u]) {
        vis[v] += vis[u];
        vis[u] = 0;
        G[v].erase(u);
        if(G[v].size() == 1) {
          q.push(v);
        }
      }
    }  
    ll ans = 0;
    for(int i = 1; i <= n; i++) {
      ans += (vis[i] - 1) * vis[i] / 2;
      ans += vis[i] * (n - vis[i]);
    } 
    cout << ans << '\n';
  }  
  return 0;
}