题意
传送门 Codeforces 1325F Ehab’s Last Theorem
题解
令 s q = ⌈ n ⌉ sq = \lceil \sqrt{n}\rceil sq=⌈n⌉,构造 D F S DFS DFS 树,若存在返祖边包含至少 s q sq sq 个节点,则找到了一个满足要求的简单环。
否则,任一节点的返祖边及其与父节点的连边的数量至多为 s q − 2 sq-2 sq−2;故将任一节点包含于独立集,至多需要排除 s q − 2 sq-2 sq−2 个节点。则自底向上不断向独立集添加点,至少可以包含 s q sq sq 个点(也可以通过图染色进行构造)。总时间复杂度 O ( n + m ) O(n+m) O(n+m)。
独立集点数的下界证明如下:
s
q
−
1
<
n
≤
s
q
⇒
n
s
q
−
1
>
n
n
=
n
sq-1<\sqrt{n}\leq sq\ \Rightarrow \frac{n}{sq-1}>\frac{n}{\sqrt{n}}=\sqrt{n}
sq−1<n≤sq ⇒sq−1n>nn=n
根据顶函数的单调非减性质,得到
⌈
n
s
q
−
1
⌉
≥
⌈
n
⌉
\lceil\frac{n}{sq-1}\rceil\geq \lceil \sqrt{n}\rceil
⌈sq−1n⌉≥⌈n⌉
#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = l, _ = r; i < _; ++i)
#define pb push_back
typedef long long ll;
const int MAXN = 1E5 + 5;
int N, M, dep[MAXN], par[MAXN], sz;
vector<int> G[MAXN], rec;
bool found, ban[MAXN];
void dfs(int u, int p, int d)
{
dep[u] = d, par[u] = p;
for (auto &v : G[u])
{
if (dep[v] == -1)
{
dfs(v, u, d + 1);
}
else if (v != p)
{
if (found)
continue;
if (dep[u] - dep[v] + 1 >= sz)
{
found = 1;
vector<int> res;
res.pb(v);
int w = u;
while (w != v)
res.pb(w), w = par[w];
cout << "2\n";
cout << (int)res.size() << '\n';
for (auto &v : res)
cout << v + 1 << ' ';
cout << '\n';
}
}
}
if (!ban[u])
{
if ((int)rec.size() < sz)
rec.pb(u);
for (auto &v : G[u])
ban[v] = 1;
}
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> N >> M;
int lb = 0, ub = 1000;
while (ub - lb > 1)
{
int mid = (lb + ub) >> 1;
if (mid * mid < N)
lb = mid;
else
ub = mid;
}
sz = ub;
rep(i, 0, M)
{
int u, v;
cin >> u >> v;
--u, --v;
G[u].pb(v), G[v].pb(u);
}
memset(dep, -1, sizeof(dep));
dfs(0, -1, 0);
if (!found)
{
cout << "1\n";
for (auto &v : rec)
cout << v + 1 << ' ';
cout << '\n';
}
return 0;
}