题意:给一个基环图(比一棵树多一条边的图),问图中简单路径的个数
思路:
基环图有且只有一个环,现讨论图中两个不同的点
(1)两个点都在环上,有2条路径
(2)一个在环上,一个不在环上,有2条路径
(3)都不在环上,但在同一棵子树中,有1条路径
(4)都不在环上,也不在同一棵子树中,2条路经
所以单独算出(3)就可以了,用(n - 1)* n 减去
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const ll inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const ll N = 2e5 + 10;
vector<ll>mp[N];
ll n, deg[N], cnt;
bool vis[N];
void topo() {
queue<ll>q;
for(ll i = 1; i <= n; ++i)
if(deg[i] == 1) deg[i]--, q.push(i);
while(!q.empty()) {
ll tp = q.front();
q.pop();
vis[tp] = 1;
ll sz = mp[tp].size();
for(ll i = 0; i < sz; ++i) {
ll v = mp[tp][i];
if(vis[v]) continue;
deg[v]--;
if(deg[v] == 1) q.push(v), deg[v]--;
}
}
}
void dfs(int u, int fa) {
cnt++;
int siz = mp[u].size();
for(int i = 0; i < siz; ++i) {
int v = mp[u][i];
if(v == fa || deg[v]) continue;
dfs(v, u);
}
}
int main() {
ll t, u, v;
scanf("%lld", &t);
while(t--) {
scanf("%lld", &n);
for(ll i = 1; i <= n; ++i) mp[i].clear();
for(ll i = 1; i <= n; ++i) deg[i] = 0;
for(ll i = 1; i <= n; ++i) {
scanf("%lld%lld", &u, &v);
mp[u].emplace_back(v);
mp[v].emplace_back(u);
deg[u]++, deg[v]++;
}
for(ll i = 1; i <= n; ++i) vis[i] = 0;
topo();
ll ans = (n - 1) * n;
for(int i = 1; i <= n; ++i) {
if(deg[i]) {
cnt = 0, dfs(i, 0);
ans -= cnt * (cnt - 1) / 2;
}
}
printf("%lld\n", ans);
}
return 0;
}