# 基环树是什么?

基环树其实是图
给一棵树加上一条边,那么树就会产生唯一的一个环,这样的图就叫基环树
如果是森林,那么可以是多个基环树

# 基环树森林

# 基环树的性格(bushi

内 / 外向基环树其实都是有向图

# 内向基环树

每个点的出度都只为 11,且环外点指向环内点

# 外向基环树

每个点的入度都只为 11,且环内点指向环外点

# 例题

# Directed Roads

# 题目大意

nn 个点和 nn 条边,第 ii 条边连接了 ii 点和 aia_i 点,每条边都需要指定一个方向,问有多少种指定方向的方案使得图中不出现
(此环非彼环,是可以沿着边一圈的环)

# 数据范围

  • 2n21052 \le n \le 2·10^5

# 样例

# 输入

IN
1
2
3
2 3 1

# 输出

OUT
1
6

# 样例说明

# 题解

把点集分为环上的点不在环上的点两部分考虑,假设第 ii 个环上有 wiw_i 个点 z

  • 不在环上的点,边的方向任意选,也就是 2nwi2^{n - \sum{w_i}} 种方案
  • 在环上的点,只有两种可能会构成环 12...wi11 \to 2 \to ... \to w_i \to 112...wi11 \leftarrow 2 \leftarrow ... \leftarrow w_i \leftarrow 1,也就是,对于一个环而言,有 2wi22^{w_i} - 2 种方案
    共计:(2nwi)(2^{n - \sum{w_i}}) · (2wi2)(\prod{2^{w_i} - 2}) 种方案
    那么怎么求数和环内点数呢?
    C++
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    int depth[N];
    int st[N];
    vector<int> g[N];
    vector<int> r;

    void dfs(int u, int dep) {
    depth[u] = dep, st[u] = 1;

    for (auto &v : g[u]) {
    if (st[v] == 0)
    dfs(v, dep + 1);
    else if (st[v] == 1)
    r.push_back(depth[u] - depth[v] + 1);
    }

    st[u] = 2;
    }
  • 复杂度 O(N+E)O(N+E)
    • NN:点数
    • EE:边数

总结一下就可以得到 ACAC 代码哩

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
int depth[N];
int st[N];
vector<int> g[N];
vector<int> r;

int n;

int qmi(int x, int y) {
int res = 1;
while (y) {
if (y & 1)
res = res * x % MOD;
x = x * x % MOD, y >>= 1;
}

return res % MOD;
}

void dfs(int u, int dep) {
depth[u] = dep, st[u] = 1;

for (auto &v : g[u]) {
if (st[v] == 0)
dfs(v, dep + 1);
else if (st[v] == 1)
r.push_back(depth[u] - depth[v] + 1);
}

st[u] = 2;
}

void solve () {
cin >> n;
for (int i = 1, x; i <= n; i++)
cin >> x, g[i].push_back(x);

for (int i = 1; i <= n; i++)
if (depth[i] == 0)
dfs(i, 1);

int sum = 0, res = 1;
for (int t : r)
sum += t, res = res * (qmi(2, t) - 2 + MOD) % MOD;

cout << res * qmi(2, n - sum) % MOD << endl;
}

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

duoxichangan 微信支付

微信支付

duoxichangan 支付宝

支付宝