Codeforces Round #686 (Div. 3)
Codeforces Round #686 (Div. 3)
E. Number of Simple Paths
思路:因为这个图的边和点的数量相等,所以保证图上只有一个简单环,我们找到这个环,把这个环上所有的边断掉,然后将这个环上所有点连向一个虚拟点 \(0\) ,以 \(0\) 为根(写的时候不用这么麻烦,这么说只是为了便于理解),统计父节点是 \(0\) 的所有子树的 \(sz_1, sz_2, sz_3 .... sz_k\) ,那么答案就是 \((\sum_{i = 1}^k \sum_{j = i + 1}^k sz_i * sz_j + n * (n - 1) / 2)\)
我是用 \(dfs\) 树实现的,下面是代码
#include <bits/stdc++.h>
using namespace std;
#define lc (rt << 1)
#define rc ((rt << 1) | 1)
#define fi first
#define se second
#define pb push_back
#define pii pair<int, int>
#define rep(i, l, r) for (int i = (l); i <= (r); ++i)
#define per(i, r, l) for (int i = (r); i >= (l); --i)
#define PE(i, u) for (int i = head[u]; i != -1; i = edge[i].next)
typedef long long LL;
const int maxn = 1e6 + 20;
const int mod = 1e9 + 7;
int n, m;
struct Edge
{
int to, next;
} edge[maxn * 2];
int k, head[maxn];
void add(int a, int b){
edge[k].to = b;
edge[k].next = head[a];
head[a] = k++;
}
int d[maxn], dp[maxn], sz[maxn];
LL ans = 0;
int sum;
void dfs(int u, int fa){
sz[u] = 1;
PE(i, u){
int to = edge[i].to;
if(to == fa) continue;
if(!d[to]) {
d[to] = d[u] + 1;
dfs(to, u);
dp[u] += dp[to];
sz[u] += sz[to];
} else if(d[to] > d[u]) dp[u]--;
else if(d[to] < d[u]) {
dp[u]++;
}
}
if(dp[u]) {
ans += 1LL * (sum - sz[u]) * sz[u];
sum -= sz[u];
sz[u] = 0;
}
}
int main(int argc, char const *argv[])
{
int t;
scanf("%d", &t);
while(t--){
scanf("%d", &n);
sum = n;
ans = 0;
ans = 1LL * n * (n - 1) / 2;
rep(i, 1, n){
dp[i] = sz[i] = d[i] = 0;
head[i] = -1;
}
rep(i, 1, n){
int u, v;
scanf("%d%d", &u, &v);
add(u, v), add(v, u);
}
d[1] = 1;
dfs(1, 0);
printf("%lld\n", ans);
}
return 0;
}