DFS找最小环
DFS找最小环
对于无向无权图,可以直接使用dfs来找最小环,并找出环上的点
例题
http://codeforces.com/contest/1364/problem/D
题意
给出一张图和一个参数k,可以选择完成两个任务中的一个
- 找到一个独立集恰好有$\lceil k/2 \rceil $个点
- 找到一个简单环,环长最多为k
题解
对于树形结构,直接判断一下完成任务1即可
对于非树形结构,一定有环,找到最小环,如果最小环长度小于等于k,直接完成任务2,否则在环上隔一个取一个完成任务1即可
代码
在dfs中,满足dep[u]-dep[v]>0即为找到一个环,使用pre记录一下即可还原环上的点
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
struct READ {
inline char read() {
#ifdef Artoriax
return getchar();
#endif
const int LEN = 1 << 18 | 1;
static char buf[LEN], *s, *t;
return (s == t) && (t = (s = buf) + fread(buf, 1, LEN, stdin)), s == t ? -1 : *s++;
}
inline READ & operator >> (char *s) {
char ch;
while (isspace(ch = read()) && ~ch);
while (!isspace(ch) && ~ch) *s++ = ch, ch = read(); *s = '\0';
return *this;
}
inline READ & operator >> (string &s) {
s = ""; char ch;
while (isspace(ch = read()) && ~ch);
while (!isspace(ch) && ~ch) s += ch, ch = read();
return *this;
}
template <typename _Tp> inline READ & operator >> (_Tp&x) {
char ch, flag;
for(ch = read(),flag = 0; !isdigit(ch) && ~ch; ch = read()) flag |= ch == '-';
for(x = 0; isdigit(ch); ch = read()) x = x * 10 + (ch ^ '0');
flag && (x = -x);
return *this;
}
} in;
const int N = 2e5 + 50;
vector<int> G[N];
int pos;
int dep[N];
int pre[N];
int mn = 1e9;
void dfs(int u, int fa, int d) {
pre[u] = fa;
dep[u] = d;
for (int v : G[u]) {
if (v == fa) continue;
if (!dep[v]) dfs(v, u, d + 1);
else if (dep[u] - dep[v] > 0 && dep[u] - dep[v] + 1 < mn){
mn = dep[u] - dep[v] + 1;
pos = u;
}
}
}
int main() {
int n, m, k; in >> n >> m >> k;
for (int i = 1; i <= m; i++) {
int u, v; in >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1, 0, 1);
if (m == n - 1) {
vector<int> res[2];
for (int i = 1; i <= n; i++) {
res[dep[i] & 1].push_back(i);
}
puts("1");
int sz = (k + 1) / 2;
if (res[0].size() < res[1].size()) {
for (int i = 0; i < sz; i++) printf("%d ", res[1][i]);
}
else {
for (int i = 0; i < sz; i++) printf("%d ", res[0][i]);
}
return 0;
}
if (mn <= k) {
puts("2");
printf("%d\n", mn);
while (mn--) {
printf("%d ", pos);
pos = pre[pos];
}
}
else {
puts("1");
for (int i = 0; i < (k + 1) / 2; i++) {
printf("%d ", pos);
pos = pre[pre[pos]];
}
}
return 0;
}