https://codeforces.ml/contest/1364/problem/D
/* 给出一张 n 个点的无向连通图和一个常数 k。 你需要解决以下两个问题的任何一个: 1. 找出一个大小为 k/2 (向上取整)的独立集。 2. 找出一个大小不超过 k 的环。 独立集是一个点的集合,满足其中任意两点之间在原图上没有边直接相连。 3≤k≤n≤105,n?1≤m≤2×105 其实就是找出无向图中的简单环(不含重边,环内部非相邻点之间没有边) 你找到一个长度大于k的环,直接取不相邻的间隔点按情况1处理即可。 找到长度小于k的环,直接可作为结果按情况2输出。 没找到简单环的情况,就说明这是一颗树,按深度奇偶性分成两部分,取元素多的那一部分按情况一处理。 */ #include<bits/stdc++.h> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define rush! ios::sync_with_stdio(false);cin.tie(0); const int inf = 0x3f3f3f3f; const long long linf = 0x3f3f3f3f3f3f3f3f; vector<int >g[200005]; typedef long long ll; const int N=200005; int ind; int dfn[N],fa[N]; int loop[N],cnt; int vis[N]; int huan; ll t1=0; ll t2=0; queue<int >q1; queue<int >q2; void loops(int u){ dfn[u]=++ind; for(auto i:g[u]){ if(i==fa[u])continue; if(dfn[i]){ if(dfn[i]<dfn[u])continue; loop[++cnt]=i; vis[i]=1; for(;i!=u;i=fa[i]){ loop[++cnt]=fa[i]; vis[fa[i]]=1; } if(!huan) huan=cnt; return ; } else{ fa[i]=u; loops(i); if(huan)return ; } } } void dfs(int u,int fa,int ceng){ if(ceng%2){ q1.push(u); t1++; } else{ t2++; q2.push(u); } for(auto i:g[u]){ if(i!=fa){ dfs(i,u,ceng+1); } } } void solve(){ int n,m,k; cin>>n>>m>>k; for(int i=1;i<=n;i++){ ind=0; dfn[i]=0,fa[i]=0; loop[i]=0; cnt=0; vis[i]=0; g[i].clear(); } for(int i=1;i<=m;i++){ int x,y; cin>>x>>y; g[x].push_back(y); g[y].push_back(x); } ll ans=0; loops(1); if(huan<=k&&huan){ cout<<2<<endl; cout<<huan<<endl; for(int i=1;i<=huan;i++){ cout<<loop[i]<<" "; } } else if(huan==0){ cout<<1<<endl; dfs(1,-1,1); int f=0; if(t1>t2){ while(f<(k-1)/2+1){ f++; cout<<q1.front()<<" "; q1.pop(); } } else{ while(f<(k-1)/2+1){ f++; cout<<q2.front()<<" "; q2.pop(); } } } else{ cout<<1<<endl; int cnt=0; int f=0; for(int i=1;i<=huan;i++){ if(i%2){ f++; cout<<loop[i]<<" "; } if(f==(k-1)/2+1)break; } } cout<<endl; } int main(){ int t=1; //cin>>t; // cout<<C(5,2); while(t--){ solve(); } }