#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
typedef long long ll;
const int p=1e8+7;
int ans1;
int ans2;
int ans3;
int n,m,x,y,k;
vector<int>v[1001000],ans;
int d[100010],vis[100100],nd;
void dfs(int x,int fa)
{
ans.push_back(x);
d[x]=ans.size();//x在ans中的位置
for(auto i:v[x])
{
if(i==fa)
continue;
if(!d[i])//如果没有遍历过,往下遍历
dfs(i,x);
else if(d[x]-d[i]+1<=k&&d[x]-d[i]+1>=0)//如果已经遍历过,说明是个环,判断环的大小
{
printf("2\n%d\n",d[x]-d[i]+1);//环的大小 通过在ans中的编号搞出来
for(int j=d[i]-1; j<d[x]; j++) //输出环,因为在vector种下标的缘故,整体要往左移动一个单位
printf("%d ",ans[j]);
printf("\n");
exit(0);
}
}
//如果x没有遍历过 记得把和x相邻的 都标记,为了第一种答案
if(!vis[x])
for(auto i:v[x])
vis[i]=1;
//相当于反向回溯,因为他要的独立集,是不相邻的,处理最后一个元素时,把和她相邻的都标记,然后把最后一个删掉,删掉的记作x,然后再往回
//如果此时最后的 和 x 相邻,那么已经被标记过,也就不能再执行上面的语句了,就直接被删掉
//这样不会出现重复被标记的问题
ans.pop_back();
}
int main()
{
cin>>n>>m>>k;
nd=k/2;
if(k%2)
nd++;
for(int i=1; i<=m; i++)
{
scanf("%d%d",&x,&y);
v[x].push_back(y),v[y].push_back(x);
}
dfs(1,0);
printf("1\n");
for(int i=1; i<=n&&nd; i++)
if(!vis[i])
printf("%d ",i),nd--;
}