F. Ehab's Last Theorem dfs树!!!
题目大意:
给你一个图,构造一个序列,这个序列有两种构造方法,任选其一构造即可。
- 找到一个独立集,独立集包含 \(\left \lceil \ \sqrt[]{n}\ \right \rceil\) 个点。
- 找到一个简单环,这个环上的点至少 \(\left \lceil \ \sqrt[]{n}\ \right \rceil\) 个,且按照环的顺序输出序列。
如果是第一种,则第一行先输出1,第二行输出这个序列,如果是第二种,则先输出2,再输出序列。
题解:
首先建一棵 \(dfs\) 树, \(dfs\) 树有一个性质就是:
每一个节点只会连向它的后代节点,或者说每一个回边都是后代连向他的祖先节点。
\(dfs\) 树构建完之后,对于一个节点,它的子节点之间是不会有边相连的。
知道这个性质之后,我们可以尝试去找简单环,这个在一棵树上还是很好找的。
-
对这棵树进行 \(dfs\) 如果出现回边,那就说明构成了一个简单环,就判断这个简单环的节点数是不是大于\(\left \lceil \ \sqrt[]{n}\ \right \rceil\) ,大于则可以之间输出答案。
-
如果没有找到满足条件的简单环,那肯定可以找到一个满足条件的独立集,这是为什么呢?
因为没有两个点之间的深度大于等于 \(\left \lceil \ \sqrt[]{n}\ \right \rceil - 1\) 的环,所以剩下的两个节点之间的深度肯定是小于等于 \(\left \lceil \ \sqrt[]{n}\ \right \rceil - 2\) 的,所以我们选完一个节点之后,最多会删除 \(\left \lceil \ \sqrt[]{n}\ \right \rceil - 1\) 个点 ,
$ \left \lceil \frac{n}{ \left \lceil \ \sqrt[]{n}\ \right \rceil - 1 } \right \rceil $ >= \(\left \lceil \ \sqrt[]{n}\ \right \rceil\),所以肯定可以找到满足条件的独立集。
接下来解释一下为什么是最多呢?因为对于一个节点来说,它的子节点之间肯定不会有边相连,所以如果我选中的值往上走走不了\(\left \lceil \ \sqrt[]{n}\ \right \rceil\) ,则不需要删\(\left \lceil \ \sqrt[]{n}\ \right \rceil - 1\) 这么多的节点数。
#include <bits/stdc++.h>
using namespace std;
const int maxn=4e5+10;
int head[maxn],cnt;
struct node{
int v,nxt;
node(int v=0,int nxt=0):v(v),nxt(nxt){}
}e[maxn];
void add(int u,int v){
e[++cnt]=node(v,head[u]);
head[u]=cnt;
e[++cnt]=node(u,head[v]);
head[v]=cnt;
}
int n,m,tot=0;
int dep[maxn],fa[maxn],ver[maxn];
void dfs(int u){
ver[++tot]=u;
dep[u]=dep[fa[u]]+1;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==fa[u]) continue;
if(!dep[v]){
fa[v]=u;
dfs(v);
}
else{
long long l=dep[u]-dep[v]+1;
if(l*l>=n){
printf("2\n%d\n",l);
int x=u;
while(x!=v){
printf("%d ",x);
x=fa[x];
}
printf("%d\n",v);
exit(0);
}
}
}
}
bool vis[maxn];
int main(){
cnt=0;
scanf("%d%d",&n,&m);
for(int i=1,u,v;i<=m;i++){
scanf("%d%d",&u,&v);
add(u,v);
}
dfs(1);
int l=1;
for(;l*l<n;l++);
int cur=l;
printf("1\n");
for(int i=n;i>=1;i--){
int u=ver[i];
if(vis[u]) continue;
l--;
printf("%d%c",u,l?' ':'\n');
if(!l) break;
for(int i=1;i<=cur-1;i++){
vis[u]=1;
u=fa[u];
}
}
return 0;
}