[CF1454E] Number of Simple Paths - 拓扑排序,基环树
Description
一颗基环树,请你计算出这张图中长度大于等于 1 的不同的简单路径的数量。
Solution
如果在环的一个子树内,那么只有一条路径
其它情况都有两条
所以做一个容斥即可
如何优雅地找一个环?
可以用类似拓扑排序的方法,用类似 BFS 的实现比较简单。每次将叶子添加到队列中,然后删掉与他相连的边,如果产生了新的叶子就加入到队列中。我们发现,最后所有的子树都会被删除,我们把它们的大小收缩的环上。
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
int n;
cin >> n;
vector<set<int>> g(n + 2);
vector<int> siz(n + 2, 1);
for (int i = 1; i <= n; i++)
{
int u, v;
cin >> u >> v;
g[u].insert(v);
g[v].insert(u);
}
queue<int> que;
for (int i = 1; i <= n; i++)
if (g[i].size() == 1)
que.push(i);
while (que.size())
{
int p = que.front();
que.pop();
int q = *g[p].begin();
g[p].erase(q);
g[q].erase(p);
siz[q] += siz[p];
siz[p] = 0;
if (g[q].size() == 1)
que.push(q);
}
int ans = 0;
for (int i = 1; i <= n; i++)
ans += siz[i] * (siz[i] - 1) / 2;
ans = n * (n - 1) - ans;
cout << ans << endl;
}
signed main()
{
ios::sync_with_stdio(false);
int t;
cin >> t;
while (t--)
solve();
}