基环树

简介

关于如何找环,直接 dfs 即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int a[maxn], cnt; 
bool Dfs(int u, int fa) {
static bool vis[maxn] = { 0 };
static stack<int> S;
vis[u] = 1; S.push(u);
for (auto v : G[u]) {
if (v == fa) continue;
if (vis[v]) {
int t;
do {
t = S.top(); S.pop();
a[++cnt] = t;
} while (t != v);
return 1;
}
if (Dfs(v, u)) return 1;
} S.pop(); return 0;
}

例题

  1. 简要题意:给定一棵基环树,求从 1 开始 dfs 所能得到的字典序最小的 dfs

    n5×105

    简要题解:注意到如果是一棵树的情况,那么我们从 1 开始 dfs 每次走编号最小的节点即可

    考虑基环树的情况,发现最终一定有一条边没有经过,所以我们枚举删边即可

    时间复杂度 O(n2)

    Luogu P5022 [NOIP2018 提高组] 旅行

  2. 简要题意:给定一个 n 个点的基环树,现在有 m 次询问,每次询问给定三元组 (x,y,z),求一个点 k,使得 d(x,k)+d(y,k)+d(z,k) 最小,d(x,y) 表示 xy 的最短路径

    n105

    简要题解:如果不是基环树,那么答案显然是 d(x,y)+d(x,z)+d(y,z)2,否则我们按照一种比较神奇的建树方法,建三棵树,然后枚举 x,y,z 分别在哪棵树上即可

    建图大概是这样:

    xzkRzj.png牛客 contest 12986E Shortest Path Sum