题意:
给你一张图,你有两种选择:
1.找到里面一个大小为
⌈
n
⌉
\lceil\sqrt{n}\rceil
⌈n⌉的独立集
2.找到里面一个长度大于等于
⌈
n
⌉
\lceil\sqrt{n}\rceil
⌈n⌉的简单环
题解:
很久没写程序了,都有点生疏。
那么这道题一开始如果当成一张图去想的话我觉得很难想,但是众所周知连通图图其实可以看成在一棵生成树上加边。那么选择2就很简单了:
对于找到的生成树上深度相差这么多的两个连通的点就是所要求的简单环
如果没有呢,那么我们将每个点的深度取模
⌈
n
⌉
−
1
\lceil\sqrt{n}\rceil-1
⌈n⌉−1,那么其中至少有一个深度的点的数量>=
⌈
n
⌉
\lceil\sqrt{n}\rceil
⌈n⌉。这就是鸽巢原理。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int num[N],cnt;
struct node{
int to,next;
}e[N*2];
int tot,head[N],dep[N],mod;
void add(int x,int y){
e[tot].to=y;
e[tot].next=head[x];
head[x]=tot++;
}
stack<int>st;
void dfs(int x,int fa){
dep[x]=dep[fa]+1;
num[dep[x]%mod]++;
st.push(x);
for(int i=head[x];~i;i=e[i].next){
int ne=e[i].to;
if(ne==fa)continue;
if(dep[ne]||ne==1){
if(dep[x]-dep[ne]+1>=cnt){
printf("2\n%d\n",dep[x]-dep[ne]+1);
while(1){
printf("%d\n",st.top());
if(st.top()==ne)break;
st.pop();
}
exit(0);
}
continue;
}
dfs(ne,x);
}
st.pop();
}
int main()
{
memset(head,-1,sizeof(head));
int n,m,x,y;
scanf("%d%d",&n,&m);
mod=sqrt(n);
if(mod*mod!=n)mod++;
cnt=mod;
mod--;
for(int i=1;i<=m;i++)
scanf("%d%d",&x,&y),add(x,y),add(y,x);
dep[0]=-1;
dfs(1,0);
int ans;
for(int i=0;i<mod;i++){
if(num[i]>=cnt){
printf("1\n");
for(int j=1;j<=n;j++){
if(dep[j]%mod==i)
printf("%d\n",j),cnt--;
if(!cnt)
exit(0);
}
}
}
}