参考:CF1325F Ehab’s Last Theorem(dfs树
简单定义为一颗由
d
f
s
dfs
dfs 生成而来的树
一颗
d
f
s
dfs
dfs树的边分为树边和非树边
深色的是树边,浅色的是非树边
d
f
s
dfs
dfs树的性质:
①:每条非树边
(
u
,
v
)
(u, v)
(u,v) 都连向子树中某个点,且一定具有祖先关系
②:子树之间不存在非树边
因此
u
u
u 到
v
v
v 在树上的链 与 非树边
(
u
,
v
)
(u, v)
(u,v) 可以形成一个环,环的大小为
∣
d
e
p
[
u
]
−
d
e
p
[
v
]
∣
+
1
|dep[u] - dep[v]| + 1
∣dep[u]−dep[v]∣+1
由此可以找出无向图的环,也可以找最大环和最小环
例题: Codeforces Round #649 (Div. 2) D. Ehab’s Last Corollary
题目大意:
n
n
n 个点
m
m
m 条边的无向图,给定一个
k
k
k,找出满足下面任何一个条件的答案:
一个独立集,点数恰为
⌈
k
2
⌉
\lceil\frac{k}{2}\rceil
⌈2k⌉
一个环,点数不超过
k
k
k
解题思路:
其实很好想,分三种情况:
①:能在图中找到一个点数不超过
k
k
k 个的环,则输出这个环
②:能找到环,但最小环的点数大于
k
k
k,则最小环上可以找到点数恰为
⌈
k
2
⌉
\lceil\frac{k}{2}\rceil
⌈2k⌉ 的独立集
③:无环,则原图为二分图,直接染色找独立集即可
发现 ② 和 ③ 可以用分层染色处理,关键是怎么找最小环
因此直接用
d
f
s
dfs
dfs树处理即可
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const int maxn = 2e5 + 5;
int n, m, k, flag;
int dep[maxn], fa[maxn];
vector <int> g[maxn], col[2], cyc;
void find(int u, int v){
while(u ^ v){
cyc.push_back(u);
u = fa[u];
}
cyc.push_back(v);
}
void dfs(int u, int f){
fa[u] = f; dep[u] = dep[f] + 1;
col[dep[u] & 1].push_back(u);
for(auto v : g[u]){
if(v == f) continue;
if(!dep[v]) dfs(v, u);
else if(dep[u] > dep[v]){
if(dep[u] - dep[v] + 1 <= k){
if(flag) continue;
flag = 1; find(u, v);
}
}
}
}
signed main() {
scanf("%d%d%d", &n, &m, &k);
for(int i=1, u, v; i<=m; i++) {
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1, 0);
if(flag) {
printf("2\n%d\n", cyc.size());
for(auto i : cyc) printf("%d ", i);
} else {
int num = (k + 1) / 2;
int op = col[0].size() > col[1].size() ? 0 : 1;
printf("1\n");
for(auto i : col[op]) {
printf("%d ", i); num--;
if(num == 0) break;
}
}
}