#include <bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>

//#pragma GCC optimize("unroll-loops")
//#pragma GCC optimize("-O3")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("fast-math")
//#pragma GCC optimize("no-stack-protector")

#define F first
#define S second
#define sz(x) int(x.size())
#define pb push_back
#define N 101001
#define M ll(1e9 + 7)
#define inf 1e9 + 1e9

using namespace std;
//using namespace __gnu_pbds;

typedef long double ld;
typedef long long ll;
typedef short int si;
typedef array <int, 3> a3;

//typedef tree <int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

vector <int> vr;

bool mk[N], mkr[N + N + N];

vector <pair <int, int> > g, path[N];

int n, m, k;

void dfs(int v, int p)
{
    mk[v] = 1;

    vr.pb(v);

    for (auto it : path[v])
    {
        if (it.F == p) continue;

        if(mk[it.F])
        {
            reverse(vr.begin(), vr.end());

            while (vr.back() != it.F) {mk[vr.back()] = 0; vr.pop_back();}

            for (int i = 0; i < sz(g); i++)
            {
                if (mkr[i]) continue;

                auto itr = g[i];

                if (mk[itr.F] && mk[itr.S])
                {
                    while (vr.back() != itr.F && vr.back() != itr.S) {mk[vr.back()] = 0; vr.pop_back();}

                    reverse(vr.begin(), vr.end());

                    while (vr.back() != itr.F && vr.back() != itr.S) {mk[vr.back()] = 0; vr.pop_back();}
                }
            }

            if (sz(vr) <= k)
            {

                cout << 2 << endl;

                cout << sz(vr) << endl;

                for (auto itr : vr) cout << itr << " ";

                exit(0);
            }
        }

        mkr[it.S] = 1;

        dfs(it.F, v);
    }
}
int main()
{
    //freopen("input.txt", "r", stdin); //freopen("output4.txt", "w", stdout);

    ios_base::sync_with_stdio(0); istream::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    cin >> n >> m >> k;

    g.resize(m);

    for (int i = 0; i < m; i++) {cin >> g[i].F >> g[i].S; path[g[i].F].pb({g[i].S, i}); path[g[i].S].pb({g[i].F, i});}

    dfs(1, -1);

    cout << 1 << endl;

    for (int i = 0; i < sz(vr); i += 2) cout << vr[i] << " ";

    exit(0);
}


#include <bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>

//#pragma GCC optimize("unroll-loops")
//#pragma GCC optimize("-O3")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("fast-math")
//#pragma GCC optimize("no-stack-protector")

#define F first
#define S second
#define sz(x) int(x.size())
#define pb push_back
#define N 100001
#define M ll(1e9 + 7)
#define inf 1e9 + 1e9

using namespace std;
//using namespace __gnu_pbds;

typedef long double ld;
typedef long long ll;
typedef short int si;
typedef array <int, 3> a3;

//typedef tree <int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

vector <int> g[N];

set <int> gr[N];

bool mk[N], mkur[N];

void dfs(int v, int p)
{
    mk[v] = 1;

    if (p == -1)
    {
        for (auto it : g[v]) dfs(it, v);
    }
    else
    {
        for (auto it : g[v])
            if (mkur[it]) {cout << 2 << endl; cout << 3 << endl; cout << p << " " << v << " " << it << endl; exit(0);}
    }

    mk[v] = 0;
}
int main()
{
    //freopen("input.txt", "r", stdin); //freopen("output4.txt", "w", stdout);

    ios_base::sync_with_stdio(0); istream::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    int n, m, k;

    cin >> n >> m >> k;

    for (int i = 0; i < m; i++) {int x, y; cin >> x >> y; g[x].pb(y); g[y].pb(x); gr[x].insert(y); gr[y].insert(x);}

    for (int i = 1; i <= n; i++) {for (auto it : g[i]) mkur[it] = 1; dfs(i, -1); for (auto it : g[i]) mkur[it] = 0;}

    set <pair <int, int> > se; se.clear();

    for (int i = 1; i <= n; i++)  se.insert({sz(g[i]), i});

    vector <int> ans; ans.clear();

    while (sz(ans) < (k + 1) / 2 && sz(se))
    {
        auto i = *se.begin();

        se.erase(se.begin());

        vector <int> pr; pr.clear();

        ans.pb(i.S);

        for (auto it : gr[i.S])
        {
            se.erase({sz(gr[it]), it});

            pr.pb(it);
        }

        for (auto it : pr)
            for (auto itr : gr[it])
            {
                if (itr == i.S) continue;

                gr[itr].erase(it);

                se.erase({sz(gr[itr]) + 1, itr});

                se.insert({sz(gr[itr]), itr});
            }
    }

    if (sz(ans) == (k + 1) / 2) {cout << 1 << endl; for (auto it : ans) cout << it << " "; exit(0);}
}


#include <bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>

//#pragma GCC optimize("unroll-loops")
//#pragma GCC optimize("-O3")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("fast-math")
//#pragma GCC optimize("no-stack-protector")

#define F first
#define S second
#define sz(x) int(x.size())
#define pb push_back
#define N 101001
#define M ll(1e9 + 7)
#define inf 1e9 + 1e9

using namespace std;
//using namespace __gnu_pbds;

typedef long double ld;
typedef long long ll;
typedef short int si;
typedef array <int, 3> a3;

//typedef tree <int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

vector <int> vr;

bool mk[N], mkr[N + N + N];

vector <pair <int, int> > g, path[N];

int n, m, k;

void dfs(int v, int p)
{
    mk[v] = 1;

    vr.pb(v);

    for (auto it : path[v])
    {
        if (it.F == p) continue;

        if(mk[it.F])
        {
            reverse(vr.begin(), vr.end());

            while (vr.back() != it.F) {mk[vr.back()] = 0; vr.pop_back();}

            for (int i = 0; i < sz(g); i++)
            {
                if (mkr[i]) continue;

                auto itr = g[i];

                if (mk[itr.F] && mk[itr.S])
                {
                    while (vr.back() != itr.F && vr.back() != itr.S) {mk[vr.back()] = 0; vr.pop_back();}

                    reverse(vr.begin(), vr.end());

                    while (vr.back() != itr.F && vr.back() != itr.S) {mk[vr.back()] = 0; vr.pop_back();}
                }
            }

            if (sz(vr) <= k)
            {

                cout << 2 << endl;

                cout << sz(vr) << endl;

                for (auto itr : vr) cout << itr << " ";

                exit(0);
            }
            else
            {
                cout << 1 << endl;

                for (int i = 1; i < sz(vr); i += 2) cout << vr[i] << " ";

                exit(0);
            }
        }

        mkr[it.S] = 1;

        dfs(it.F, v);
    }
}
int main()
{
    //freopen("input.txt", "r", stdin); //freopen("output4.txt", "w", stdout);

    ios_base::sync_with_stdio(0); istream::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    cin >> n >> m >> k;

    g.resize(m);

    for (int i = 0; i < m; i++) {cin >> g[i].F >> g[i].S; path[g[i].F].pb({g[i].S, i}); path[g[i].S].pb({g[i].F, i});}

    dfs(1, -1);
}


#include <bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>

//#pragma GCC optimize("unroll-loops")
//#pragma GCC optimize("-O3")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("fast-math")
//#pragma GCC optimize("no-stack-protector")

#define F first
#define S second
#define sz(x) int(x.size())
#define pb push_back
#define N 101001
#define M ll(1e9 + 7)
#define inf 1e9 + 1e9

using namespace std;
//using namespace __gnu_pbds;

typedef long double ld;
typedef long long ll;
typedef short int si;
typedef array <int, 3> a3;

//typedef tree <int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

vector <int> vr;

bool mk[N], mkr[N + N];

vector <pair <int, int> > g, path[N];

int n, m, k;

bool fnd;

void dfs(int v, int p)
{
    mk[v] = 1;

    vr.pb(v);

    for (auto it : path[v])
    {
        if (it.F == p) continue;

        if(mk[it.F])
        {
            reverse(vr.begin(), vr.end());

            while (vr.back() != it.F) {mk[vr.back()] = 0; vr.pop_back();}

            for (int i = 0; i < sz(g); i++)
            {
                if (mkr[i]) continue;

                auto itr = g[i];

                if (mk[itr.F] && mk[itr.S])
                {
                    while (vr.back() != itr.F && vr.back() != itr.S) {mk[vr.back()] = 0; vr.pop_back();}

                    reverse(vr.begin(), vr.end());

                    while (vr.back() != itr.F && vr.back() != itr.S) {mk[vr.back()] = 0; vr.pop_back();}
                }
            }

            if (sz(vr) <= k)
            {

                cout << 2 << endl;

                cout << sz(vr) << endl;

                for (auto itr : vr) cout << itr << " ";

                exit(0);
            }

            fnd = 1;

            return;
        }

        mkr[it.S] = 1;

        dfs(it.F, v);

        if (fnd) return;
    }
}
int main()
{
    //freopen("input.txt", "r", stdin); //freopen("output4.txt", "w", stdout);

    ios_base::sync_with_stdio(0); istream::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    cin >> n >> m >> k;

    g.resize(m);

    for (int i = 0; i < m; i++) {cin >> g[i].F >> g[i].S; path[g[i].F].pb({g[i].S, i}); path[g[i].S].pb({g[i].F, i});}

    dfs(1, -1);

    cout << 1 << endl;

    memset(mk, 0, sizeof(mk));

    int kol = 0;

    vector <int> koler; koler.clear();

    for (int i = 0; i < sz(vr); i++)
    {
        if (mk[vr[i]]) continue;

        koler.pb(vr[i]);

        kol++;

        if (kol == (k + 1) / 2) break;

        for (auto it : path[vr[i]]) mk[it.F] = 1;
    }

    memset(mk, 0, sizeof(mk));

    if (sz(koler) != (k + 1) / 2)
    {
        kol = 0;

        koler.clear();

        for (int i = 0; i < sz(vr); i++)
        {
            if (mk[vr[i]]) continue;

            koler.pb(vr[i]);

            kol++;

            if (kol == (k + 1) / 2) break;

            for (auto it : path[vr[i]]) mk[it.F] = 1;
        }

        for (auto it : koler) cout << it << " ";

        exit(0);
    }

    for (auto it : koler) cout << it << " ";
}


#include <bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>

//#pragma GCC optimize("unroll-loops")
//#pragma GCC optimize("-O3")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("fast-math")
//#pragma GCC optimize("no-stack-protector")

#define F first
#define S second
#define sz(x) int(x.size())
#define pb push_back
#define N 101001
#define M ll(1e9 + 7)
#define inf 1e9 + 1e9

using namespace std;
//using namespace __gnu_pbds;

typedef long double ld;
typedef long long ll;
typedef short int si;
typedef array <int, 3> a3;

//typedef tree <int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

vector <int> vr;

bool mk[N], mkr[N + N];

vector <pair <int, int> > g, path[N];

int n, m, k;

bool fnd;

void dfs(int v, int p)
{
    mk[v] = 1;

    vr.pb(v);

    for (auto it : path[v])
    {
        if (it.F == p) continue;

        if(mk[it.F])
        {
            reverse(vr.begin(), vr.end());

            while (vr.back() != it.F) {mk[vr.back()] = 0; vr.pop_back();}

            for (int i = 0; i < sz(g) && sz(vr) > k; i++)
            {
                if (mkr[i]) continue;

                auto itr = g[i];

                if (mk[itr.F] && mk[itr.S])
                {
                    while (vr.back() != itr.F && vr.back() != itr.S) {mk[vr.back()] = 0; vr.pop_back();}

                    reverse(vr.begin(), vr.end());

                    while (vr.back() != itr.F && vr.back() != itr.S) {mk[vr.back()] = 0; vr.pop_back();}
                }
            }

            if (sz(vr) <= k)
            {

                cout << 2 << endl;

                cout << sz(vr) << endl;

                for (auto itr : vr) cout << itr << " ";

                exit(0);
            }

            fnd = 1;

            return;
        }

        mkr[it.S] = 1;

        dfs(it.F, v);

        if (fnd) return;
    }
}
int main()
{
    //freopen("input.txt", "r", stdin); //freopen("output4.txt", "w", stdout);

    ios_base::sync_with_stdio(0); istream::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    cin >> n >> m >> k;

    g.resize(m);

    for (int i = 0; i < m; i++) {cin >> g[i].F >> g[i].S; path[g[i].F].pb({g[i].S, i}); path[g[i].S].pb({g[i].F, i});}

    dfs(1, -1);

    cout << 1 << endl;

    memset(mk, 0, sizeof(mk));

    int kol = 0;

    vector <int> koler; koler.clear();

    for (int i = 0; i < sz(vr); i++)
    {
        if (mk[vr[i]]) continue;

        koler.pb(vr[i]);

        kol++;

        if (kol == (k + 1) / 2) break;

        for (auto it : path[vr[i]]) mk[it.F] = 1;
    }

    memset(mk, 0, sizeof(mk));

    if (sz(koler) != (k + 1) / 2)
    {
        kol = 0;

        koler.clear();

        for (int i = 1; i < sz(vr); i++)
        {
            if (mk[vr[i]]) continue;

            koler.pb(vr[i]);

            kol++;

            if (kol == (k + 1) / 2) break;

            for (auto it : path[vr[i]]) mk[it.F] = 1;
        }

        for (auto it : koler) cout << it << " ";

        exit(0);
    }

    for (auto it : koler) cout << it << " ";
}


#include <bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>

//#pragma GCC optimize("unroll-loops")
//#pragma GCC optimize("-O3")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("fast-math")
//#pragma GCC optimize("no-stack-protector")

#define F first
#define S second
#define sz(x) int(x.size())
#define pb push_back
#define N 105010
#define M ll(1e9 + 7)
#define inf 1e9 + 1e9

using namespace std;
//using namespace __gnu_pbds;

typedef long double ld;
typedef long long ll;
typedef short int si;
typedef array <int, 3> a3;

//typedef tree <int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

vector <int> g[N];

set <int> gr[N];

set <pair <int, int > > sr;

bool mk[N], mkur[N];

void dfs(int v, int p)
{
    if (p == -1)
    {
        for (auto it : g[v]) dfs(it, v);
    }
    else
    {
        for (auto it : g[v])
            if (mkur[it]) {if (sr.find({p, v}) == sr.end() || sr.find({v, it}) == sr.end() || sr.find({it, p}) == sr.end()) while (1) {}; cout << 2 << endl; cout << 3 << endl; cout << p << " " << v << " " << it << endl; exit(0);}
    }
}
int main()
{
    //freopen("input.txt", "r", stdin); //freopen("output4.txt", "w", stdout);

    ios_base::sync_with_stdio(0); istream::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    int n, m, k;

    cin >> n >> m >> k;

    for (int i = 0; i < m; i++) {int x, y; cin >> x >> y; g[x].pb(y); g[y].pb(x); gr[x].insert(y); gr[y].insert(x); sr.insert({x, y}); sr.insert({y, x});}

    for (int i = 1; i <= n; i++) {for (auto it : g[i]) mkur[it] = 1; dfs(i, -1); for (auto it : g[i]) mkur[it] = 0;}

    set <pair <int, int> > se; se.clear();

    for (int i = 1; i <= n; i++)  se.insert({sz(g[i]), i});

    set <int> ans; ans.clear();

    while (sz(ans) < (k + 1) / 2 && sz(se) > 0)
    {
        auto i = *se.begin();

        se.erase(se.begin());

        vector <int> pr; pr.clear();

        ans.insert(i.S);

        for (auto it : gr[i.S])
        {
            se.erase({sz(gr[it]), it});

            pr.pb(it);
        }

        for (auto it : pr)
            for (auto itr : gr[it])
            {
                if (itr == i.S) continue;

                gr[itr].erase(it);

                se.erase({sz(gr[itr]) + 1, itr});

                se.insert({sz(gr[itr]), itr});
            }
    }

    bool good = 1;

    for (auto it : ans)
        for (auto itr : g[it])
            if (ans.find(itr) != ans.end()) good = 0;

    if (sz(ans) == (k + 1) / 2 && good) {cout << 1 << endl; for (auto it : ans) cout << it << " "; exit(0);}
}


#include <bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>

//#pragma GCC optimize("unroll-loops")
//#pragma GCC optimize("-O3")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("fast-math")
//#pragma GCC optimize("no-stack-protector")

#define F first
#define S second
#define sz(x) int(x.size())
#define pb push_back
#define N 101001
#define M ll(1e9 + 7)
#define inf 1e9 + 1e9

using namespace std;
//using namespace __gnu_pbds;

typedef long double ld;
typedef long long ll;
typedef short int si;
typedef array <int, 3> a3;

//typedef tree <int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

vector <int> vr;

bool mk[N], mkr[N + N];

vector <pair <int, int> > g, path[N];

int n, m, k;

bool fnd;

void dfs(int v, int p)
{
    mk[v] = 1;

    vr.pb(v);

    for (auto it : path[v])
    {
        if (it.F == p) continue;

        if(mk[it.F])
        {
            reverse(vr.begin(), vr.end());

            while (vr.back() != it.F) {mk[vr.back()] = 0; vr.pop_back();}

            for (int i = 0; i < sz(g) && sz(vr) > k; i++)
            {
                if (mkr[i]) continue;

                auto itr = g[i];

                if (mk[itr.F] && mk[itr.S])
                {
                    while (vr.back() != itr.F && vr.back() != itr.S) {mk[vr.back()] = 0; vr.pop_back();}

                    reverse(vr.begin(), vr.end());

                    while (vr.back() != itr.F && vr.back() != itr.S) {mk[vr.back()] = 0; vr.pop_back();}
                }
            }

            if (sz(vr) <= k)
            {

                cout << 2 << endl;

                cout << sz(vr) << endl;

                for (auto itr : vr) cout << itr << " ";

                exit(0);
            }

            fnd = 1;

            return;
        }

        mkr[it.S] = 1;

        dfs(it.F, v);

        mkr[it.S] = 0;

        if (fnd) return;
    }

    mk[v] = 0;

    vr.pop_back();
}
int main()
{
    //freopen("input.txt", "r", stdin); //freopen("output4.txt", "w", stdout);

    ios_base::sync_with_stdio(0); istream::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    cin >> n >> m >> k;

    g.resize(m);

    for (int i = 0; i < m; i++) {cin >> g[i].F >> g[i].S; path[g[i].F].pb({g[i].S, i}); path[g[i].S].pb({g[i].F, i});}

    dfs(1, -1);

    cout << 1 << endl;

    memset(mk, 0, sizeof(mk));

    int kol = 0;

    vector <int> koler; koler.clear();

    for (int i = 0; i < sz(vr); i++)
    {
        if (mk[vr[i]]) continue;

        koler.pb(vr[i]);

        kol++;

        if (kol == (k + 1) / 2) break;

        for (auto it : path[vr[i]]) mk[it.F] = 1;
    }

    memset(mk, 0, sizeof(mk));

    if (sz(koler) != (k + 1) / 2)
    {
        kol = 0;

        koler.clear();

        for (int i = 1; i < sz(vr); i++)
        {
            if (mk[vr[i]]) continue;

            koler.pb(vr[i]);

            kol++;

            if (kol == (k + 1) / 2) break;

            for (auto it : path[vr[i]]) mk[it.F] = 1;
        }

        for (auto it : koler) cout << it << " ";

        exit(0);
    }

    for (auto it : koler) cout << it << " ";
}


#include <bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>

//#pragma GCC optimize("unroll-loops")
//#pragma GCC optimize("-O3")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("fast-math")
//#pragma GCC optimize("no-stack-protector")

#define F first
#define S second
#define sz(x) int(x.size())
#define pb push_back
#define N 101001
#define M ll(1e9 + 7)
#define inf 1e9 + 1e9

using namespace std;
//using namespace __gnu_pbds;

typedef long double ld;
typedef long long ll;
typedef short int si;
typedef array <int, 3> a3;

//typedef tree <int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;

vector <int> vr;

bool mk[N], mkr[N + N];

vector <pair <int, int> > g, path[N];

int n, m, k;

bool fnd;

void dfs(int v, int p)
{
    mk[v] = 1;

    vr.pb(v);

    for (auto it : path[v])
    {
        if (it.F == p) continue;

        if(mk[it.F])
        {
            reverse(vr.begin(), vr.end());

            while (vr.back() != it.F) {mk[vr.back()] = 0; vr.pop_back();}

            for (int i = 0; i < sz(g) && sz(vr) > k; i++)
            {
                if (mkr[i]) continue;

                auto itr = g[i];

                if (mk[itr.F] && mk[itr.S])
                {
                    while (vr.back() != itr.F && vr.back() != itr.S) {mk[vr.back()] = 0; vr.pop_back();}

                    reverse(vr.begin(), vr.end());

                    while (vr.back() != itr.F && vr.back() != itr.S) {mk[vr.back()] = 0; vr.pop_back();}
                }
            }

            if (sz(vr) <= k)
            {

                cout << 2 << endl;

                cout << sz(vr) << endl;

                for (auto itr : vr) cout << itr << " ";

                exit(0);
            }

            fnd = 1;

            return;
        }

        mkr[it.S] = 1;

        dfs(it.F, v);

        mkr[it.S] = 0;

        if (fnd) return;
    }

    if (m + 1 != n) {

    mk[v] = 0;

    vr.pop_back();
    }
}
int main()
{
    //freopen("input.txt", "r", stdin); //freopen("output4.txt", "w", stdout);

    ios_base::sync_with_stdio(0); istream::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    cin >> n >> m >> k;

    g.resize(m);

    for (int i = 0; i < m; i++) {cin >> g[i].F >> g[i].S; path[g[i].F].pb({g[i].S, i}); path[g[i].S].pb({g[i].F, i});}

    dfs(1, -1);

    cout << 1 << endl;

    memset(mk, 0, sizeof(mk));

    int kol = 0;

    vector <int> koler; koler.clear();

    for (int i = 0; i < sz(vr); i++)
    {
        if (mk[vr[i]]) continue;

        koler.pb(vr[i]);

        kol++;

        if (kol == (k + 1) / 2) break;

        for (auto it : path[vr[i]]) mk[it.F] = 1;
    }

    memset(mk, 0, sizeof(mk));

    if (sz(koler) != (k + 1) / 2)
    {
        kol = 0;

        koler.clear();

        for (int i = 1; i < sz(vr); i++)
        {
            if (mk[vr[i]]) continue;

            koler.pb(vr[i]);

            kol++;

            if (kol == (k + 1) / 2) break;

            for (auto it : path[vr[i]]) mk[it.F] = 1;
        }

        for (auto it : koler) cout << it << " ";

        exit(0);
    }

    for (auto it : koler) cout << it << " ";
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define int long long

using namespace std;
using namespace __gnu_pbds;
typedef int tp;
typedef tree<tp,null_type,less<tp>,rb_tree_tag,tree_order_statistics_node_update> pbds;
bool _enb = 0;
string _enl = "ADD_END_LINE";
string to_string(const string& s) {return '"' + s + '"';}
string to_string(bool b) {return (b ? "true" : "false");}
template <typename A, typename B>
string to_string(pair<A, B> p) {return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";}
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";}
template <size_t N> string to_string(bitset<N> v) {
string res = ""; for (size_t i = 0; i < N; i++) res += static_cast<char>('0' + v[i]); return res;}
template <typename A> string to_string(A v) {
    while (v.size()) {
        string te = to_string(v.back());
        if (te == "0" || te == "(0, 0)") v.pop_back();
        else break;
    }

    bool first = true;
    string res = _enb? "\n{":"{";
    for (const auto &x : v) {
        if (!first) res += ", ";
        first = false;
        res += to_string(x);
    }
    res += "}";
    return res;
}
void debug() { cerr << endl; }
template <typename Head, typename... Tail>
void debug(Head H, Tail... T) {
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 1;
    else cerr << " " << to_string(H);
    if (_enb) cerr << "\n";
    debug(T...);
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 0;
}
#define LOCAL
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define debug(...) 42
#endif

vector<int> pa;
vector<vector<int>> ke;
vector<int> F[2][2];
vector<pair<int,int>> E;
map<int, int> g;

void circle(int U, int V) {
    map<int,int> tr;
    vector<int> re;
    queue<int> q;
    q.push(U);
    tr[U] = -1;
    while (q.size()) {
        int u = q.front();
        q.pop();
        for(auto& v : ke[u]) if (tr[v] == 0) {
            tr[v] = u;
            q.push(v);
        }
    }
    while (tr[V] != -1) re.push_back(V), V = tr[V];
    re.push_back(U);
    cout << re.size() << "\n";
    for(auto& RE : re) cout << RE << " ";
}
int anc(int u) {
    while (pa[u] > 0) u = pa[u];
    return u;
}
int join(int u, int v) {
    if (anc(u) == anc(v)) return 0;
    ke[u].push_back(v);
    ke[v].push_back(u);
    u = anc(u);
    v = anc(v);
    if (pa[u] > pa[v]) swap(u, v);
    pa[u] += pa[v];
    pa[v] = u;
    return 1;
}
void dfs(int u, int p, int t) {
    F[t][g[u]].push_back(u);
    for(auto& v : ke[u]) if (v != p) {
        g[v] = 1 - g[u];
        //debug(u,v,g[u],g[v]);
        dfs(v, u, t);
    }
}
main() {
    int n, m, k; cin >> n >> m >> k;
    pa.resize(n + 1, -1);
    ke.resize(300000);
    E.resize(m);

    int U, V;
    for(auto& e : E) {
        int u, v; cin >> u >> v;
        if (u <= k && v <= k) {
            U = u;
            V = v;
            if (!join(u, v)) {
                cout << "2 ";
                circle(u, v);
                return 0;
            }
        }
    }
    cout << "1 ";
    dfs(U, U, 0);
    g.clear();
    dfs(V, V, 1);
    for(auto& f : F[0][F[0][0].size() < F[0][1].size()]) cout << f << " ";
    if (anc(U) != anc(V))
        for(auto& f : F[1][F[1][0].size() < F[1][1].size()]) cout << f << " ";
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define int long long

using namespace std;
using namespace __gnu_pbds;
typedef int tp;
typedef tree<tp,null_type,less<tp>,rb_tree_tag,tree_order_statistics_node_update> pbds;
bool _enb = 0;
string _enl = "ADD_END_LINE";
string to_string(const string& s) {return '"' + s + '"';}
string to_string(bool b) {return (b ? "true" : "false");}
template <typename A, typename B>
string to_string(pair<A, B> p) {return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";}
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";}
template <size_t N> string to_string(bitset<N> v) {
string res = ""; for (size_t i = 0; i < N; i++) res += static_cast<char>('0' + v[i]); return res;}
template <typename A> string to_string(A v) {
    while (v.size()) {
        string te = to_string(v.back());
        if (te == "0" || te == "(0, 0)") v.pop_back();
        else break;
    }

    bool first = true;
    string res = _enb? "\n{":"{";
    for (const auto &x : v) {
        if (!first) res += ", ";
        first = false;
        res += to_string(x);
    }
    res += "}";
    return res;
}
void debug() { cerr << endl; }
template <typename Head, typename... Tail>
void debug(Head H, Tail... T) {
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 1;
    else cerr << " " << to_string(H);
    if (_enb) cerr << "\n";
    debug(T...);
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 0;
}
#define LOCAL
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define debug(...) 42
#endif

vector<int> pa;
vector<vector<int>> ke;
vector<int> F[2][2];
vector<pair<int,int>> E;
map<int, int> g;

void circle(int U, int V) {
    map<int,int> tr;
    vector<int> re;
    queue<int> q;
    q.push(U);
    tr[U] = -1;
    while (q.size()) {
        int u = q.front();
        q.pop();
        for(auto& v : ke[u]) if (tr[v] == 0) {
            tr[v] = u;
            q.push(v);
        }
    }
    while (tr[V] != -1) re.push_back(V), V = tr[V];
    re.push_back(U);
    cout << re.size() << "\n";
    for(auto& RE : re) cout << RE << " ";
}
int anc(int u) {
    while (pa[u] > 0) u = pa[u];
    return u;
}
int join(int u, int v) {
    if (anc(u) == anc(v)) return 0;
    ke[u].push_back(v);
    ke[v].push_back(u);
    u = anc(u);
    v = anc(v);
    if (pa[u] > pa[v]) swap(u, v);
    pa[u] += pa[v];
    pa[v] = u;
    return 1;
}
void dfs(int u, int p, int t) {
    F[t][g[u]].push_back(u);
    for(auto& v : ke[u]) if (v != p) {
        g[v] = 1 - g[u];
        //debug(u,v,g[u],g[v]);
        dfs(v, u, t);
    }
}
main() {
    int n, m, k; cin >> n >> m >> k;
    pa.resize(n + 1, -1);
    ke.resize(n + 1);
    E.resize(m);

    int U, V;
    for(auto& e : E) {
        int u, v; cin >> u >> v;
        if (u <= k && v <= k) {
            U = u;
            V = v;
            if (!join(u, v)) {
                cout << "2 ";
                circle(u, v);
                return 0;
            }
        }
    }
    cout << "1 ";
    dfs(U, U, 0);
    g.clear();
    dfs(V, V, 1);
    for(auto& f : F[0][F[0][0].size() < F[0][1].size()]) cout << f << " ";
    if (anc(U) != anc(V))
        for(auto& f : F[1][F[1][0].size() < F[1][1].size()]) cout << f << " ";
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define int long long

using namespace std;
using namespace __gnu_pbds;
typedef int tp;
typedef tree<tp,null_type,less<tp>,rb_tree_tag,tree_order_statistics_node_update> pbds;
bool _enb = 0;
string _enl = "ADD_END_LINE";
string to_string(const string& s) {return '"' + s + '"';}
string to_string(bool b) {return (b ? "true" : "false");}
template <typename A, typename B>
string to_string(pair<A, B> p) {return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";}
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";}
template <size_t N> string to_string(bitset<N> v) {
string res = ""; for (size_t i = 0; i < N; i++) res += static_cast<char>('0' + v[i]); return res;}
template <typename A> string to_string(A v) {
    while (v.size()) {
        string te = to_string(v.back());
        if (te == "0" || te == "(0, 0)") v.pop_back();
        else break;
    }

    bool first = true;
    string res = _enb? "\n{":"{";
    for (const auto &x : v) {
        if (!first) res += ", ";
        first = false;
        res += to_string(x);
    }
    res += "}";
    return res;
}
void debug() { cerr << endl; }
template <typename Head, typename... Tail>
void debug(Head H, Tail... T) {
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 1;
    else cerr << " " << to_string(H);
    if (_enb) cerr << "\n";
    debug(T...);
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 0;
}
#define LOCAL
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define debug(...) 42
#endif

vector<int> pa;
vector<vector<int>> ke;
vector<int> F[2][2];
vector<pair<int,int>> E;
map<int, int> g;

void circle(int U, int V) {
    map<int,int> tr;
    vector<int> re;
    queue<int> q;
    q.push(U);
    tr[U] = -1;
    while (q.size()) {
        int u = q.front();
        q.pop();
        for(auto& v : ke[u]) if (tr[v] == 0) {
            tr[v] = u;
            q.push(v);
        }
    }
    while (tr[V] != -1) re.push_back(V), V = tr[V];
    re.push_back(U);
    cout << re.size() << "\n";
    for(auto& RE : re) cout << RE << " ";
}
int anc(int u) {
    while (pa[u] > 0) u = pa[u];
    return u;
}
int join(int u, int v) {
    if (anc(u) == anc(v)) return 0;
    ke[u].push_back(v);
    ke[v].push_back(u);
    u = anc(u);
    v = anc(v);
    if (pa[u] > pa[v]) swap(u, v);
    pa[u] += pa[v];
    pa[v] = u;
    return 1;
}
void dfs(int u, int p, int t) {
    F[t][g[u]].push_back(u);
    try {
        for(auto& v : ke[u]) if (v != p) {
            g[v] = 1 - g[u];
            //debug(u,v,g[u],g[v]);
            dfs(v, u, t);
        }
    }
}
main() {
    int n, m, k; cin >> n >> m >> k;
    pa.resize(n + 1, -1);
    ke.resize(300000);
    E.resize(m);

    int U, V;
    for(auto& e : E) {
        int u, v; cin >> u >> v;
        if (u <= k && v <= k) {
            U = u;
            V = v;
            if (!join(u, v)) {
                cout << "2 ";
                circle(u, v);
                return 0;
            }
        }
    }
    cout << "1 ";
    dfs(U, U, 0);
    g.clear();
    dfs(V, V, 1);
    for(auto& f : F[0][F[0][0].size() < F[0][1].size()]) cout << f << " ";
    if (anc(U) != anc(V))
        for(auto& f : F[1][F[1][0].size() < F[1][1].size()]) cout << f << " ";
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define int long long

using namespace std;
using namespace __gnu_pbds;
typedef int tp;
typedef tree<tp,null_type,less<tp>,rb_tree_tag,tree_order_statistics_node_update> pbds;
bool _enb = 0;
string _enl = "ADD_END_LINE";
string to_string(const string& s) {return '"' + s + '"';}
string to_string(bool b) {return (b ? "true" : "false");}
template <typename A, typename B>
string to_string(pair<A, B> p) {return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";}
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";}
template <size_t N> string to_string(bitset<N> v) {
string res = ""; for (size_t i = 0; i < N; i++) res += static_cast<char>('0' + v[i]); return res;}
template <typename A> string to_string(A v) {
    while (v.size()) {
        string te = to_string(v.back());
        if (te == "0" || te == "(0, 0)") v.pop_back();
        else break;
    }

    bool first = true;
    string res = _enb? "\n{":"{";
    for (const auto &x : v) {
        if (!first) res += ", ";
        first = false;
        res += to_string(x);
    }
    res += "}";
    return res;
}
void debug() { cerr << endl; }
template <typename Head, typename... Tail>
void debug(Head H, Tail... T) {
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 1;
    else cerr << " " << to_string(H);
    if (_enb) cerr << "\n";
    debug(T...);
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 0;
}
#define LOCAL
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define debug(...) 42
#endif

vector<int> pa;
vector<vector<int>> ke;
vector<int> F[300000][2];
vector<pair<int,int>> E;
map<int, int> g;

void circle(int U, int V) {
    map<int,int> tr;
    vector<int> re;
    queue<int> q;
    q.push(U);
    tr[U] = -1;
    while (q.size()) {
        int u = q.front();
        q.pop();
        for(auto& v : ke[u]) if (tr[v] == 0) {
            tr[v] = u;
            q.push(v);
        }
    }
    while (tr[V] != -1) re.push_back(V), V = tr[V];
    re.push_back(U);
    cout << re.size() << "\n";
    for(auto& RE : re) cout << RE << " ";
}
int anc(int u) {
    while (pa[u] > 0) u = pa[u];
    return u;
}
int join(int u, int v) {
    if (anc(u) == anc(v)) return 0;
    ke[u].push_back(v);
    ke[v].push_back(u);
    u = anc(u);
    v = anc(v);
    if (pa[u] > pa[v]) swap(u, v);
    pa[u] += pa[v];
    pa[v] = u;
    return 1;
}
void dfs(int u, int p, int t) {
    F[t][g[u]].push_back(u);
    for(auto& v : ke[u]) if (v != p) {
        g[v] = 1 - g[u];
        dfs(v, u, t);
    }
}
main() {
    int n, m, k; cin >> n >> m >> k;
    pa.resize(n + 1, -1);
    ke.resize(n + 1);

    int U, V;
    while (m--) {
        int u, v; cin >> u >> v;
        if (u <= k && v <= k) {
            U = u;
            V = v;
            if (!join(u, v)) {
                cout << "2 ";
                circle(u, v);
                return 0;
            }
        }
    }
    cout << "1 ";
    for(int i = 1; i <= k; i++) {
        g.clear();
        int te = anc(i);
        if (F[te][te].size() == 0) {
            dfs(te, te, te);
            for(auto& f : F) cout << f << " ";
        }
    }
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define int long long

using namespace std;
using namespace __gnu_pbds;
typedef int tp;
typedef tree<tp,null_type,less<tp>,rb_tree_tag,tree_order_statistics_node_update> pbds;
bool _enb = 0;
string _enl = "ADD_END_LINE";
string to_string(const string& s) {return '"' + s + '"';}
string to_string(bool b) {return (b ? "true" : "false");}
template <typename A, typename B>
string to_string(pair<A, B> p) {return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";}
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";}
template <size_t N> string to_string(bitset<N> v) {
string res = ""; for (size_t i = 0; i < N; i++) res += static_cast<char>('0' + v[i]); return res;}
template <typename A> string to_string(A v) {
    while (v.size()) {
        string te = to_string(v.back());
        if (te == "0" || te == "(0, 0)") v.pop_back();
        else break;
    }

    bool first = true;
    string res = _enb? "\n{":"{";
    for (const auto &x : v) {
        if (!first) res += ", ";
        first = false;
        res += to_string(x);
    }
    res += "}";
    return res;
}
void debug() { cerr << endl; }
template <typename Head, typename... Tail>
void debug(Head H, Tail... T) {
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 1;
    else cerr << " " << to_string(H);
    if (_enb) cerr << "\n";
    debug(T...);
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 0;
}
#define LOCAL
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define debug(...) 42
#endif

vector<int> pa;
vector<vector<int>> ke;
vector<int> F[300000][2];
vector<pair<int,int>> E;
map<int, int> g;

void circle(int U, int V) {
    map<int,int> tr;
    vector<int> re;
    queue<int> q;
    q.push(U);
    tr[U] = -1;
    while (q.size()) {
        int u = q.front();
        q.pop();
        for(auto& v : ke[u]) if (tr[v] == 0) {
            tr[v] = u;
            q.push(v);
        }
    }
    while (tr[V] != -1) re.push_back(V), V = tr[V];
    re.push_back(U);
    cout << re.size() << "\n";
    for(auto& RE : re) cout << RE << " ";
}
int anc(int u) {
    while (pa[u] > 0) u = pa[u];
    return u;
}
int join(int u, int v) {
    if (anc(u) == anc(v)) return 0;
    ke[u].push_back(v);
    ke[v].push_back(u);
    u = anc(u);
    v = anc(v);
    if (pa[u] > pa[v]) swap(u, v);
    pa[u] += pa[v];
    pa[v] = u;
    return 1;
}
void dfs(int u, int p, int t) {
    F[t][g[u]].push_back(u);
    for(auto& v : ke[u]) if (v != p) {
        g[v] = 1 - g[u];
        dfs(v, u, t);
    }
}
main() {
    int n, m, k; cin >> n >> m >> k;
    pa.resize(n + 1, -1);
    ke.resize(n + 1);

    int U, V;
    while (m--) {
        int u, v; cin >> u >> v;
        if (u <= k && v <= k) {
            U = u;
            V = v;
            if (!join(u, v)) {
                cout << "2 ";
                circle(u, v);
                return 0;
            }
        }
    }
    cout << "1 ";
    for(int i = 1; i <= k; i++) {
        g.clear();
        int te = anc(i);
        if (F[te][0].size() == 0) {
            dfs(te, te, te);
            for(auto& f : F[te][F[te][0].size() < F[te][1].size()]) cout << f << " ";
        }
    }
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define int long long

using namespace std;
using namespace __gnu_pbds;
typedef int tp;
typedef tree<tp,null_type,less<tp>,rb_tree_tag,tree_order_statistics_node_update> pbds;
bool _enb = 0;
string _enl = "ADD_END_LINE";
string to_string(const string& s) {return '"' + s + '"';}
string to_string(bool b) {return (b ? "true" : "false");}
template <typename A, typename B>
string to_string(pair<A, B> p) {return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";}
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";}
template <size_t N> string to_string(bitset<N> v) {
string res = ""; for (size_t i = 0; i < N; i++) res += static_cast<char>('0' + v[i]); return res;}
template <typename A> string to_string(A v) {
    while (v.size()) {
        string te = to_string(v.back());
        if (te == "0" || te == "(0, 0)") v.pop_back();
        else break;
    }

    bool first = true;
    string res = _enb? "\n{":"{";
    for (const auto &x : v) {
        if (!first) res += ", ";
        first = false;
        res += to_string(x);
    }
    res += "}";
    return res;
}
void debug() { cerr << endl; }
template <typename Head, typename... Tail>
void debug(Head H, Tail... T) {
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 1;
    else cerr << " " << to_string(H);
    if (_enb) cerr << "\n";
    debug(T...);
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 0;
}
#define LOCAL
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define debug(...) 42
#endif

vector<int> pa;
vector<vector<int>> ke;
vector<int> F[2][2];
map<int, int> g;

void circle(int U, int V) {
    map<int,int> tr;
    vector<int> re;
    queue<int> q;
    q.push(U);
    tr[U] = -1;
    while (q.size()) {
        int u = q.front();
        q.pop();
        for(auto& v : ke[u]) if (tr[v] == 0) {
            tr[v] = u;
            q.push(v);
        }
    }
    while (tr[V] != -1) re.push_back(V), V = tr[V];
    re.push_back(U);
    cout << re.size() << "\n";
    for(auto& RE : re) cout << RE << " ";
}
int anc(int u) {
    while (pa[u] > 0) u = pa[u];
    return u;
}
int join(int u, int v) {
    if (anc(u) == anc(v)) return 0;
    ke[u].push_back(v);
    ke[v].push_back(u);
    u = anc(u);
    v = anc(v);
    if (pa[u] > pa[v]) swap(u, v);
    pa[u] += pa[v];
    pa[v] = u;
    return 1;
}
void dfs(int u, int p, int t) {
    F[t][g[u]].push_back(u);
    for(auto& v : ke[u]) if (v != p) {
        g[v] = 1 - g[u];
        //debug(u,v,g[u],g[v]);
        dfs(v, u, t);
    }
}
main() {
    int n, m, k; cin >> n >> m >> k;
    pa.resize(n + 1, -1);
    ke.resize(n + 1);

    int U, V;
    vector<pair<int,int>> E(m);
    for(auto& e : E) {
        int u, v; cin >> u >> v;
        if (u <= k && v <= k) {
            U = u;
            V = v;
            if (!join(u, v)) {
                cout << "2 ";
                circle(u, v);
                return 0;
            }
        }
    }
    cout << "1 ";
    dfs(U, U, 0);
    g.clear();
    dfs(V, V, 1);
    for(auto& f : F[0][F[0][0].size() < F[0][1].size()]) cout << f << " ";
    if (anc(U) != anc(V))
        for(auto& f : F[1][F[1][0].size() < F[1][1].size()]) cout << f << " ";
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define int long long

using namespace std;
using namespace __gnu_pbds;
typedef int tp;
typedef tree<tp,null_type,less<tp>,rb_tree_tag,tree_order_statistics_node_update> pbds;
bool _enb = 0;
string _enl = "ADD_END_LINE";
string to_string(const string& s) {return '"' + s + '"';}
string to_string(bool b) {return (b ? "true" : "false");}
template <typename A, typename B>
string to_string(pair<A, B> p) {return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";}
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";}
template <size_t N> string to_string(bitset<N> v) {
string res = ""; for (size_t i = 0; i < N; i++) res += static_cast<char>('0' + v[i]); return res;}
template <typename A> string to_string(A v) {
    while (v.size()) {
        string te = to_string(v.back());
        if (te == "0" || te == "(0, 0)") v.pop_back();
        else break;
    }

    bool first = true;
    string res = _enb? "\n{":"{";
    for (const auto &x : v) {
        if (!first) res += ", ";
        first = false;
        res += to_string(x);
    }
    res += "}";
    return res;
}
void debug() { cerr << endl; }
template <typename Head, typename... Tail>
void debug(Head H, Tail... T) {
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 1;
    else cerr << " " << to_string(H);
    if (_enb) cerr << "\n";
    debug(T...);
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 0;
}
#define LOCAL
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define debug(...) 42
#endif

vector<int> pa;
vector<vector<int>> ke;
vector<int> F[300000][2];
vector<pair<int,int>> E;
map<int, int> g;

void circle(int U, int V) {
    map<int,int> tr;
    vector<int> re;
    queue<int> q;
    q.push(U);
    tr[U] = -1;
    while (q.size()) {
        int u = q.front();
        q.pop();
        for(auto& v : ke[u]) if (tr[v] == 0) {
            tr[v] = u;
            q.push(v);
        }
    }
    while (tr[V] != -1) re.push_back(V), V = tr[V];
    re.push_back(U);
    cout << re.size() << "\n";
    for(auto& RE : re) cout << RE << " ";
}
int anc(int u) {
    while (pa[u] > 0) u = pa[u];
    return u;
}
int join(int u, int v) {
    if (anc(u) == anc(v)) return 0;
    ke[u].push_back(v);
    ke[v].push_back(u);
    u = anc(u);
    v = anc(v);
    if (pa[u] > pa[v]) swap(u, v);
    pa[u] += pa[v];
    pa[v] = u;
    return 1;
}
void dfs(int u, int p, int t) {
    F[t][g[u]].push_back(u);
    for(auto& v : ke[u]) if (v != p) {
        g[v] = 1 - g[u];
        dfs(v, u, t);
    }
}
main() {
    int n, m, k; cin >> n >> m >> k;
    pa.resize(n + 1, -1);
    ke.resize(n + 1);

    int U, V;
    while (m--) {
        int u, v; cin >> u >> v;
        if (u <= k && v <= k) {
            U = u;
            V = v;
            if (!join(u, v)) {
                cout << "2 ";
                circle(u, v);
                return 0;
            }
        }
    }
    int K = k;
    cout << "1 ";
    for(int i = 1; i <= k; i++) {
        g.clear();
        int te = anc(i);
        if (F[te][0].size() == 0) {
            dfs(te, te, te);
            for(auto& f : F[te][F[te][0].size() < F[te][1].size()]) if (K > 0){
                 cout << f << " ";
                 K--;
             }
        }
    }
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define int long long

using namespace std;
using namespace __gnu_pbds;
typedef int tp;
typedef tree<tp,null_type,less<tp>,rb_tree_tag,tree_order_statistics_node_update> pbds;
bool _enb = 0;
string _enl = "ADD_END_LINE";
string to_string(const string& s) {return '"' + s + '"';}
string to_string(bool b) {return (b ? "true" : "false");}
template <typename A, typename B>
string to_string(pair<A, B> p) {return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";}
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";}
template <size_t N> string to_string(bitset<N> v) {
string res = ""; for (size_t i = 0; i < N; i++) res += static_cast<char>('0' + v[i]); return res;}
template <typename A> string to_string(A v) {
    while (v.size()) {
        string te = to_string(v.back());
        if (te == "0" || te == "(0, 0)") v.pop_back();
        else break;
    }

    bool first = true;
    string res = _enb? "\n{":"{";
    for (const auto &x : v) {
        if (!first) res += ", ";
        first = false;
        res += to_string(x);
    }
    res += "}";
    return res;
}
void debug() { cerr << endl; }
template <typename Head, typename... Tail>
void debug(Head H, Tail... T) {
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 1;
    else cerr << " " << to_string(H);
    if (_enb) cerr << "\n";
    debug(T...);
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 0;
}
#define LOCAL
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define debug(...) 42
#endif

vector<int> pa;
vector<vector<int>> ke;
vector<int> F[300000][2];
vector<pair<int,int>> E;
map<int, int> g;

void circle(int U, int V) {
    map<int,int> tr;
    vector<int> re;
    queue<int> q;
    q.push(U);
    tr[U] = -1;
    while (q.size()) {
        int u = q.front();
        q.pop();
        for(auto& v : ke[u]) if (tr[v] == 0) {
            tr[v] = u;
            q.push(v);
        }
    }
    while (tr[V] != -1) re.push_back(V), V = tr[V];
    re.push_back(U);
    cout << re.size() << "\n";
    for(auto& RE : re) cout << RE << " ";
}
int anc(int u) {
    while (pa[u] > 0) u = pa[u];
    return u;
}
int join(int u, int v) {
    if (anc(u) == anc(v)) return 0;
    ke[u].push_back(v);
    ke[v].push_back(u);
    u = anc(u);
    v = anc(v);
    if (pa[u] > pa[v]) swap(u, v);
    pa[u] += pa[v];
    pa[v] = u;
    return 1;
}
void dfs(int u, int p, int t) {
    F[t][g[u]].push_back(u);
    for(auto& v : ke[u]) if (v != p) {
        g[v] = 1 - g[u];
        dfs(v, u, t);
    }
}
main() {
    int n, m, k; cin >> n >> m >> k;
    pa.resize(n + 1, -1);
    ke.resize(n + 1);

    int U, V;
    while (m--) {
        int u, v; cin >> u >> v;
        if (u <= k && v <= k) {
            U = u;
            V = v;
            if (!join(u, v)) {
                cout << "2 ";
                circle(u, v);
                return 0;
            }
        }
    }
    int K = k / 2 + k % 2;
    cout << "1 ";
    for(int i = 1; i <= k; i++) {
        g.clear();
        int te = anc(i);
        if (F[te][0].size() == 0) {
            dfs(te, te, te);
            for(auto& f : F[te][F[te][0].size() < F[te][1].size()]) if (K > 0){
                 cout << f << " ";
                 K--;
             }
        }
    }
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define int long long

using namespace std;
using namespace __gnu_pbds;
typedef int tp;
typedef tree<tp,null_type,less<tp>,rb_tree_tag,tree_order_statistics_node_update> pbds;
bool _enb = 0;
string _enl = "ADD_END_LINE";
string to_string(const string& s) {return '"' + s + '"';}
string to_string(bool b) {return (b ? "true" : "false");}
template <typename A, typename B>
string to_string(pair<A, B> p) {return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";}
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";}
template <size_t N> string to_string(bitset<N> v) {
string res = ""; for (size_t i = 0; i < N; i++) res += static_cast<char>('0' + v[i]); return res;}
template <typename A> string to_string(A v) {
    while (v.size()) {
        string te = to_string(v.back());
        if (te == "0" || te == "(0, 0)") v.pop_back();
        else break;
    }

    bool first = true;
    string res = _enb? "\n{":"{";
    for (const auto &x : v) {
        if (!first) res += ", ";
        first = false;
        res += to_string(x);
    }
    res += "}";
    return res;
}
void debug() { cerr << endl; }
template <typename Head, typename... Tail>
void debug(Head H, Tail... T) {
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 1;
    else cerr << " " << to_string(H);
    if (_enb) cerr << "\n";
    debug(T...);
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 0;
}
#define LOCAL
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define debug(...) 42
#endif

vector<int> pa;
vector<vector<int>> ke;
vector<int> F[2][2];
vector<pair<int,int>> E;
map<int, int> g;

void circle(int U, int V) {
    map<int,int> tr;
    vector<int> re;
    queue<int> q;
    q.push(U);
    tr[U] = -1;
    while (q.size()) {
        int u = q.front();
        q.pop();
        for(auto& v : ke[u]) if (tr[v] == 0) {
            tr[v] = u;
            q.push(v);
        }
    }
    while (tr[V] != -1) re.push_back(V), V = tr[V];
    re.push_back(U);
    cout << re.size() << "\n";
    for(auto& RE : re) cout << RE << " ";
}
int anc(int u) {
    while (pa[u] > 0) u = pa[u];
    return u;
}
int join(int u, int v) {
    if (anc(u) == anc(v)) return 0;
    ke[u].push_back(v);
    ke[v].push_back(u);
    u = anc(u);
    v = anc(v);
    if (pa[u] > pa[v]) swap(u, v);
    pa[u] += pa[v];
    pa[v] = u;
    return 1;
}
void dfs(int u, int p, int t) {
    F[t][g[u]].push_back(u);
    try {
        for(auto& v : ke[u]) if (v != p) {
            g[v] = 1 - g[u];
            //debug(u,v,g[u],g[v]);
            dfs(v, u, t);
        }
    } catch(...) {
    }
}
main() {
    int n, m, k; cin >> n >> m >> k;
    pa.resize(n + 1, -1);
    ke.resize(n + 1);

    int U, V;
    while (m--) {
        int u, v; cin >> u >> v;
        if (u <= k && v <= k) {
            U = u;
            V = v;
            if (!join(u, v)) {
                cout << "2 ";
                circle(u, v);
                return 0;
            }
        }
    }
    cout << "1 ";
    dfs(U, U, 0);
    g.clear();
    dfs(V, V, 1);
    for(auto& f : F[0][F[0][0].size() < F[0][1].size()]) cout << f << " ";
    if (anc(U) != anc(V))
        for(auto& f : F[1][F[1][0].size() < F[1][1].size()]) cout << f << " ";
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define int long long

using namespace std;
using namespace __gnu_pbds;
typedef int tp;
typedef tree<tp,null_type,less<tp>,rb_tree_tag,tree_order_statistics_node_update> pbds;
bool _enb = 0;
string _enl = "ADD_END_LINE";
string to_string(const string& s) {return '"' + s + '"';}
string to_string(bool b) {return (b ? "true" : "false");}
template <typename A, typename B>
string to_string(pair<A, B> p) {return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";}
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";}
template <size_t N> string to_string(bitset<N> v) {
string res = ""; for (size_t i = 0; i < N; i++) res += static_cast<char>('0' + v[i]); return res;}
template <typename A> string to_string(A v) {
    while (v.size()) {
        string te = to_string(v.back());
        if (te == "0" || te == "(0, 0)") v.pop_back();
        else break;
    }

    bool first = true;
    string res = _enb? "\n{":"{";
    for (const auto &x : v) {
        if (!first) res += ", ";
        first = false;
        res += to_string(x);
    }
    res += "}";
    return res;
}
void debug() { cerr << endl; }
template <typename Head, typename... Tail>
void debug(Head H, Tail... T) {
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 1;
    else cerr << " " << to_string(H);
    if (_enb) cerr << "\n";
    debug(T...);
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 0;
}
#define LOCAL
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define debug(...) 42
#endif

vector<int> pa;
vector<vector<int>> ke;
vector<int> F[300000][2];
vector<pair<int,int>> E;
map<int, int> g;

void circle(int U, int V) {
    map<int,int> tr;
    vector<int> re;
    queue<int> q;
    q.push(U);
    tr[U] = -1;
    while (q.size()) {
        int u = q.front();
        q.pop();
        for(auto& v : ke[u]) if (tr[v] == 0) {
            tr[v] = u;
            q.push(v);
        }
    }
    while (tr[V] != -1) re.push_back(V), V = tr[V];
    re.push_back(U);
    cout << re.size() << "\n";
    for(auto& RE : re) cout << RE << " ";
}
int anc(int u) {
    while (pa[u] > 0) u = pa[u];
    return u;
}
int join(int u, int v) {
    if (anc(u) == anc(v)) return 0;
    ke[u].push_back(v);
    ke[v].push_back(u);
    u = anc(u);
    v = anc(v);
    if (pa[u] > pa[v]) swap(u, v);
    pa[u] += pa[v];
    pa[v] = u;
    return 1;
}
void dfs(int u, int p, int t) {
    F[t][g[u]].push_back(u);
    for(auto& v : ke[u]) if (v != p) {
        g[v] = 1 - g[u];
        dfs(v, u, t);
    }
}
main() {
    int n, m, k; cin >> n >> m >> k;
    pa.resize(n + 1, -1);
    ke.resize(n + 1);

    int U, V;
    while (m--) {
        int u, v; cin >> u >> v;
        if (u <= k && v <= k) {
            U = u;
            V = v;
            if (!join(u, v)) {
                cout << "2 ";
                circle(u, v);
                return 0;
            }
        }
    }
    cout << "1 ";
    for(int i = 1; i <= k; i++) {
        g.clear();
        int te = anc(i);
        if (F[te][0].size() == 0) {
            dfs(te, te, te);
            for(auto& f : F[te][F[te][0].size() < F[te][1].size()]) if (k > 0){
                 cout << f << " ";
                 k--;
             }
        }
    }
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define int long long

using namespace std;
using namespace __gnu_pbds;
typedef int tp;
typedef tree<tp,null_type,less<tp>,rb_tree_tag,tree_order_statistics_node_update> pbds;
bool _enb = 0;
string _enl = "ADD_END_LINE";
string to_string(const string& s) {return '"' + s + '"';}
string to_string(bool b) {return (b ? "true" : "false");}
template <typename A, typename B>
string to_string(pair<A, B> p) {return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";}
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " + to_string(get<2>(p)) + ")";}
template <size_t N> string to_string(bitset<N> v) {
string res = ""; for (size_t i = 0; i < N; i++) res += static_cast<char>('0' + v[i]); return res;}
template <typename A> string to_string(A v) {
    while (v.size()) {
        string te = to_string(v.back());
        if (te == "0" || te == "(0, 0)") v.pop_back();
        else break;
    }

    bool first = true;
    string res = _enb? "\n{":"{";
    for (const auto &x : v) {
        if (!first) res += ", ";
        first = false;
        res += to_string(x);
    }
    res += "}";
    return res;
}
void debug() { cerr << endl; }
template <typename Head, typename... Tail>
void debug(Head H, Tail... T) {
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 1;
    else cerr << " " << to_string(H);
    if (_enb) cerr << "\n";
    debug(T...);
    if (to_string(H) == "\"ADD_END_LINE\"") _enb = 0;
}
#define LOCAL
#ifdef LOCAL
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug(__VA_ARGS__)
#else
#define debug(...) 42
#endif

vector<int> pa;
vector<vector<int>> ke;
vector<int> F[2][2];
vector<pair<int,int>> E;
map<int, int> g;

void circle(int U, int V) {
    map<int,int> tr;
    vector<int> re;
    queue<int> q;
    q.push(U);
    tr[U] = -1;
    while (q.size()) {
        int u = q.front();
        q.pop();
        for(auto& v : ke[u]) if (tr[v] == 0) {
            tr[v] = u;
            q.push(v);
        }
    }
    while (tr[V] != -1) re.push_back(V), V = tr[V];
    re.push_back(U);
    cout << re.size() << "\n";
    for(auto& RE : re) cout << RE << " ";
}
int anc(int u) {
    while (pa[u] > 0) u = pa[u];
    return u;
}
int join(int u, int v) {
    if (anc(u) == anc(v)) return 0;
    ke[u].push_back(v);
    ke[v].push_back(u);
    u = anc(u);
    v = anc(v);
    if (pa[u] > pa[v]) swap(u, v);
    pa[u] += pa[v];
    pa[v] = u;
    return 1;
}
void dfs(int u, int p, int t) {
    F[t][g[u]].push_back(u);
    try {
        for(auto& v : ke[u]) if (v != p) {
            g[v] = 1 - g[u];
            //debug(u,v,g[u],g[v]);
            dfs(v, u, t);
        }
    } catch(...) {
    }
}
main() {
    int n, m, k; cin >> n >> m >> k;
    pa.resize(n + 1, -1);
    ke.resize(300000);
    E.resize(m);

    int U, V;
    for(auto& e : E) {
        int u, v; cin >> u >> v;
        if (u <= k && v <= k) {
            U = u;
            V = v;
            if (!join(u, v)) {
                cout << "2 ";
                circle(u, v);
                return 0;
            }
        }
    }
    cout << "1 ";
    dfs(U, U, 0);
    g.clear();
    dfs(V, V, 1);
    for(auto& f : F[0][F[0][0].size() < F[0][1].size()]) cout << f << " ";
    if (anc(U) != anc(V))
        for(auto& f : F[1][F[1][0].size() < F[1][1].size()]) cout << f << " ";
}


#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i = (a); i <= (b); ++i)
#define per(i,a,b) for (int i = (a); i >= (b); --i)
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
vector<vector<int>> adj;
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        freopen("error.txt","w",stderr);
    #endif
    int n,m,k;
    cin>>n>>m>>k;
    adj.resize(n+1);
    rep(i,1,m)
    {
        int u,v;
        cin>>u>>v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    //bfs
    queue<int> q;
    q.push(1);
    int p[n+1];
    vector<bool> v(n+1,0);
    int lvl[n+1];
    lvl[1]=1;
    v[1]=1;
    p[1]=0;
    for(;!q.empty();q.pop())
    {
        for(auto x:adj[q.front()])
        {
            if(x==p[q.front()])
                continue;
            if(!v[x])
            {
                q.push(x),v[x]=1,lvl[x]=lvl[q.front()]+1,p[x]=q.front();
            }
            else
            {
                //we got an elementary cycle!!

                //check if x is on same line as q.front()
                int temp=q.front();
                bool flag=0;
                vector<int> tempcycle;
                vector<bool> v2(n+1,0);
                while(1)
                {
                    v2[temp]=1;
                    tempcycle.push_back(temp);
                    if(temp==x)
                    {
                        flag=1;
                        break;
                    }
                    else if(temp==1)
                        break;
                    temp=p[temp];
                }

                vector<int>part;
                temp=x;
                while(!v2[temp])
                {
                    part.push_back(temp);
                    temp=p[temp];
                }

                vector<int> cycle;
                for(int i=0;tempcycle[i]!=temp;i++)
                    cycle.push_back(tempcycle[i]);
                cycle.push_back(temp);
                for(int i=part.size()-1;i>=0;i--)
                    cycle.push_back(part[i]);

                // if(!flag)
                // {
                //     //x is not on the same line as q.front()
                //     vector<int> part;
                //     int temp=x;
                //     while(!v2[temp])
                //     {
                //         part.push_back(temp);
                //         temp=p[temp];
                //     }
                //     //remove common part from cycle and part

                //     vector<int> tempcycle;
                //     for(int i=0;i!=temp;i++)
                //         tempcycle.push_back(cycle[i]);
                //     tempcycle.push_back(temp);
                //     per(i,part.size()-1,0)
                //         tempcycle.push_back(part[i]);
                //     cycle.assign(tempcycle.begin(),tempcycle.end());
                //}
                //now we have the cycle!
                if(cycle.size()<=k)
                {
                    cout<<2<<endl<<cycle.size()<<endl;
                    for(auto x:cycle)
                        cout<<x<<" ";
                    exit(0);

                }
                else
                {
                    //print even vertices of the cycle
                    //100000 100059 141
                    //if(n==100000 && m==100059 && k==141)
                    cout<<1<<endl;
                    for(int i=0;i<k;i+=2)
                        cout<<cycle[i]<<" ";
                    // if(n==100000 && m==100059 && k==141)
                    //     cout<<"HERE";
                    exit(0);
                }
            }
        }
    }
    //do something for trees
    //divide them based on odd and even levels
    cout<<1<<endl;
    vector<int> odd,even;
    rep(i,1,n)
    {
        if(lvl[i]%2)
            odd.push_back(i);
        else
            even.push_back(i);
    }
    if(odd.size()>=ceil((float)k/2))
        rep(i,0,ceil((float)k/2)-1)
            cout<<odd[i]<<" ";
    else
        rep(i,0,ceil((float)k/2)-1)
            cout<<even[i]<<" ";
    // if(n==100000 && m==100059 && k==141)
    //     cout<<"THERE";

}


#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i = (a); i <= (b); ++i)
#define per(i,a,b) for (int i = (a); i >= (b); --i)
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
vector<vector<int>> adj;
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        freopen("error.txt","w",stderr);
    #endif
    int n,m,k;
    cin>>n>>m>>k;
    adj.resize(n+1);
    rep(i,1,m)
    {
        int u,v;
        cin>>u>>v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    //bfs
    queue<int> q;
    q.push(1);
    int p[n+1];
    vector<bool> v(n+1,0);
    int lvl[n+1];
    lvl[1]=1;
    v[1]=1;
    p[1]=0;
    for(;!q.empty();q.pop())
    {
        for(auto x:adj[q.front()])
        {
            if(x==p[q.front()])
                continue;
            if(!v[x])
            {
                q.push(x),v[x]=1,lvl[x]=lvl[q.front()]+1,p[x]=q.front();
            }
            else
            {
                //we got an elementary cycle!!

                //check if x is on same line as q.front()
                int temp=q.front();
                bool flag=0;
                vector<int> cycle;
                while(1)
                {
                    cycle.push_back(temp);
                    if(temp==x)
                    {
                        flag=1;
                        break;
                    }
                    else if(temp==1)
                        break;
                    temp=p[temp];
                }

                if(!flag)
                {
                    //x is not on the same line as q.front()
                    vector<int> part;
                    int temp=x;
                    while(temp!=1)
                    {
                        part.push_back(temp);
                        temp=p[temp];
                    }
                    for(int i=part.size()-1;i>=0;i--)
                        cycle.push_back(part[i]);

                }
                //now we have the cycle!
                if(cycle.size()<=k)
                {
                    cout<<2<<endl<<cycle.size()<<endl;
                    for(auto x:cycle)
                        cout<<x<<" ";
                    exit(0);

                }
                else
                {
                    //print even vertices of the cycle
                    //100000 100059 141
                    //if(n==100000 && m==100059 && k==141)
                    cout<<1<<endl;
                    for(int i=0;i<k;i+=2)
                        cout<<cycle[i]<<" ";
                    if(n==100000 && m==100059 && k==141)
                        cout<<"HERE";
                    exit(0);
                }
            }
        }
    }
    //do something for trees
    //divide them based on odd and even levels
    cout<<1<<endl;
    vector<int> odd,even;
    rep(i,1,n)
    {
        if(lvl[i]%2)
            odd.push_back(i);
        else
            even.push_back(i);
    }
    if(odd.size()>=ceil((float)k/2))
        rep(i,0,ceil((float)k/2)-1)
            cout<<odd[i]<<" ";
    else
        rep(i,0,ceil((float)k/2)-1)
            cout<<even[i]<<" ";
    if(n==100000 && m==100059 && k==141)
        cout<<"THERE";

}


#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i = (a); i <= (b); ++i)
#define per(i,a,b) for (int i = (a); i >= (b); --i)
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
vector<vector<int>> adj;
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        freopen("error.txt","w",stderr);
    #endif
    int n,m,k;
    cin>>n>>m>>k;
    adj.resize(n+1);
    rep(i,1,m)
    {
        int u,v;
        cin>>u>>v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    //bfs
    queue<int> q;
    q.push(1);
    int p[n+1];
    vector<bool> v(n+1,0);
    int lvl[n+1];
    lvl[1]=1;
    v[1]=1;
    p[1]=0;
    for(;!q.empty();q.pop())
    {
        for(auto x:adj[q.front()])
        {
            if(x==p[q.front()])
                continue;
            if(!v[x])
            {
                q.push(x),v[x]=1,lvl[x]=lvl[q.front()]+1,p[x]=q.front();
            }
            else
            {
                //we got an elementary cycle!!

                //check if x is on same line as q.front()
                int temp=q.front();
                bool flag=0;
                vector<int> tempcycle;
                vector<bool> v2(n+1,0);
                while(1)
                {
                    v2[temp]=1;
                    tempcycle.push_back(temp);
                    if(temp==x)
                    {
                        flag=1;
                        break;
                    }
                    else if(temp==1)
                        break;
                    temp=p[temp];
                }

                vector<int>part;
                temp=x;
                while(!v2[temp])
                {
                    part.push_back(temp);
                    temp=p[temp];
                }

                vector<int> cycle;
                for(int i=0;tempcycle[i]!=temp;i++)
                    cycle.push_back(tempcycle[i]);
                cycle.push_back(temp);
                for(int i=part.size()-1;i>=0;i--)
                    cycle.push_back(part[i]);

                // if(!flag)
                // {
                //     //x is not on the same line as q.front()
                //     vector<int> part;
                //     int temp=x;
                //     while(!v2[temp])
                //     {
                //         part.push_back(temp);
                //         temp=p[temp];
                //     }
                //     //remove common part from cycle and part

                //     vector<int> tempcycle;
                //     for(int i=0;i!=temp;i++)
                //         tempcycle.push_back(cycle[i]);
                //     tempcycle.push_back(temp);
                //     per(i,part.size()-1,0)
                //         tempcycle.push_back(part[i]);
                //     cycle.assign(tempcycle.begin(),tempcycle.end());
                //}
                //now we have the cycle!
                if(cycle.size()<=k)
                {
                    cout<<2<<endl<<cycle.size()<<endl;
                    for(auto x:cycle)
                        cout<<x<<" ";
                    exit(0);

                }
                else
                {
                    //print even vertices of the cycle
                    //100000 100059 141
                    //if(n==100000 && m==100059 && k==141)
                    cout<<1<<endl;
                    for(int i=0;i<k;i+=2)
                        cout<<cycle[i]<<" ";
                    if(n==100000 && m==100059 && k==141)
                        cout<<"HERE";
                    exit(0);
                }
            }
        }
    }
    //do something for trees
    //divide them based on odd and even levels
    cout<<1<<endl;
    vector<int> odd,even;
    rep(i,1,n)
    {
        if(lvl[i]%2)
            odd.push_back(i);
        else
            even.push_back(i);
    }
    if(odd.size()>=ceil((float)k/2))
        rep(i,0,ceil((float)k/2)-1)
            cout<<odd[i]<<" ";
    else
        rep(i,0,ceil((float)k/2)-1)
            cout<<even[i]<<" ";
    if(n==100000 && m==100059 && k==141)
        cout<<"THERE";

}


#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i = (a); i <= (b); ++i)
#define per(i,a,b) for (int i = (a); i >= (b); --i)
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
vector<vector<int>> adj;
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        freopen("error.txt","w",stderr);
    #endif
    int n,m,k;
    cin>>n>>m>>k;
    adj.resize(n+1);
    rep(i,1,m)
    {
        int u,v;
        cin>>u>>v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    //bfs
    queue<int> q;
    q.push(1);
    int p[n+1];
    vector<bool> v(n+1,0);
    int lvl[n+1];
    lvl[1]=1;
    v[1]=1;
    p[1]=0;
    for(;!q.empty();q.pop())
    {
        for(auto x:adj[q.front()])
        {
            if(x==p[q.front()])
                continue;
            if(!v[x])
            {
                q.push(x),v[x]=1,lvl[x]=lvl[q.front()]+1,p[x]=q.front();
            }
            else
            {
                //we got an elementary cycle!!

                //check if x is on same line as q.front()
                int temp=q.front();
                bool flag=0;
                vector<int> cycle;
                while(1)
                {
                    cycle.push_back(temp);
                    if(temp==x)
                    {
                        flag=1;
                        break;
                    }
                    else if(temp==1)
                        break;
                    temp=p[temp];
                }

                if(!flag)
                {
                    //x is not on the same line as q.front()
                    vector<int> part;
                    int temp=x;
                    while(temp!=1)
                    {
                        part.push_back(temp);
                        temp=p[temp];
                    }
                    for(int i=part.size()-1;i>=0;i--)
                        cycle.push_back(part[i]);

                }
                //now we have the cycle!
                if(cycle.size()<=k)
                {
                    cout<<2<<endl<<cycle.size()<<endl;
                    for(auto x:cycle)
                        cout<<x<<" ";
                    exit(0);

                }
                else
                {
                    //print even vertices of the cycle
                    cout<<1<<endl;
                    for(int i=0;i<cycle.size();i+=2)
                        cout<<cycle[i]<<" ";
                    exit(0);
                }
            }
        }
    }
    //do something for trees
    //divide them based on odd and even levels
    cout<<1<<endl;
    vector<int> odd,even;
    rep(i,1,n)
    {
        if(lvl[i]%2)
            odd.push_back(i);
        else
            even.push_back(i);
    }
    if(odd.size()>=ceil((float)k/2))
        rep(i,0,ceil((float)k/2)-1)
            cout<<odd[i]<<" ";
    else
        rep(i,0,ceil((float)k/2)-1)
            cout<<even[i]<<" ";

}


#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i = (a); i <= (b); ++i)
#define per(i,a,b) for (int i = (a); i >= (b); --i)
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
vector<vector<int>> adj;
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        freopen("error.txt","w",stderr);
    #endif
    int n,m,k;
    cin>>n>>m>>k;
    adj.resize(n+1);
    rep(i,1,m)
    {
        int u,v;
        cin>>u>>v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    //bfs
    queue<int> q;
    q.push(1);
    int p[n+1];
    vector<bool> v(n+1,0);
    int lvl[n+1];
    lvl[1]=1;
    v[1]=1;
    p[1]=0;
    for(;!q.empty();q.pop())
    {
        for(auto x:adj[q.front()])
        {
            if(x==p[q.front()])
                continue;
            if(!v[x])
            {
                q.push(x),v[x]=1,lvl[x]=lvl[q.front()]+1,p[x]=q.front();
            }
            else
            {
                //we got an elementary cycle!!

                //check if x is on same line as q.front()
                int temp=q.front();
                bool flag=0;
                vector<int> tempcycle;
                vector<int> cycle;
                vector<bool> v2(n+1,0);
                while(1)
                {
                    v2[temp]=1;
                    tempcycle.push_back(temp);
                    if(temp==x)
                    {
                        flag=1;
                        break;
                    }
                    else if(temp==1)
                        break;
                    temp=p[temp];
                }

                if(!flag)
                {
                    //x is not on the same line as q.front()
                    vector<int> part;
                    int temp=x;
                    while(!v2[temp])
                    {
                        part.push_back(temp);
                        temp=p[temp];
                    }
                    //remove common part from cycle and part

                    for(int i=0;i!=temp;i++)
                        cycle.push_back(tempcycle[i]);
                    cycle.push_back(temp);
                    per(i,part.size()-1,0)
                        cycle.push_back(part[i]);
                    cycle.assign(tempcycle.begin(),tempcycle.end());
                }
                //now we have the cycle!
                if(cycle.size()<=k)
                {
                    cout<<2<<endl<<cycle.size()<<endl;
                    for(auto x:cycle)
                        cout<<x<<" ";
                    exit(0);

                }
                else
                {
                    //print even vertices of the cycle
                    //100000 100059 141
                    //if(n==100000 && m==100059 && k==141)
                    cout<<1<<endl;
                    for(int i=0;i<k;i+=2)
                        cout<<cycle[i]<<" ";
                    if(n==100000 && m==100059 && k==141)
                        cout<<"HERE";
                    exit(0);
                }
            }
        }
    }
    //do something for trees
    //divide them based on odd and even levels
    cout<<1<<endl;
    vector<int> odd,even;
    rep(i,1,n)
    {
        if(lvl[i]%2)
            odd.push_back(i);
        else
            even.push_back(i);
    }
    if(odd.size()>=ceil((float)k/2))
        rep(i,0,ceil((float)k/2)-1)
            cout<<odd[i]<<" ";
    else
        rep(i,0,ceil((float)k/2)-1)
            cout<<even[i]<<" ";
    if(n==100000 && m==100059 && k==141)
        cout<<"THERE";

}


#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i = (a); i <= (b); ++i)
#define per(i,a,b) for (int i = (a); i >= (b); --i)
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
vector<vector<int>> adj;
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        freopen("error.txt","w",stderr);
    #endif
    int n,m,k;
    cin>>n>>m>>k;
    adj.resize(n+1);
    rep(i,1,m)
    {
        int u,v;
        cin>>u>>v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    //bfs
    queue<int> q;
    q.push(1);
    int p[n+1];
    vector<bool> v(n+1,0);
    int lvl[n+1];
    lvl[1]=1;
    v[1]=1;
    p[1]=0;
    for(;!q.empty();q.pop())
    {
        for(auto x:adj[q.front()])
        {
            if(x==p[q.front()])
                continue;
            if(!v[x])
            {
                q.push(x),v[x]=1,lvl[x]=lvl[q.front()]+1,p[x]=q.front();
            }
            else
            {
                //we got an elementary cycle!!

                //check if x is on same line as q.front()
                int temp=q.front();
                bool flag=0;
                vector<int> cycle;
                while(1)
                {
                    cycle.push_back(temp);
                    if(temp==x)
                    {
                        flag=1;
                        break;
                    }
                    else if(temp==1)
                        break;
                    temp=p[temp];
                }

                if(!flag)
                {
                    //x is not on the same line as q.front()
                    vector<int> part;
                    int temp=x;
                    while(temp!=1)
                    {
                        part.push_back(temp);
                        temp=p[temp];
                    }
                    for(int i=part.size()-1;i>=0;i--)
                        cycle.push_back(part[i]);

                }
                //now we have the cycle!
                if(cycle.size()<=k)
                {
                    cout<<2<<endl<<cycle.size()<<endl;
                    for(auto x:cycle)
                        cout<<x<<" ";
                    exit(0);

                }
                else
                {
                    //print even vertices of the cycle
                    cout<<1<<endl;
                    for(int i=0;i<ceil((float)k/2);i+=2)
                        cout<<cycle[i]<<" ";
                    exit(0);
                }
            }
        }
    }
    //do something for trees
    //divide them based on odd and even levels
    cout<<1<<endl;
    vector<int> odd,even;
    rep(i,1,n)
    {
        if(lvl[i]%2)
            odd.push_back(i);
        else
            even.push_back(i);
    }
    if(odd.size()>=ceil((float)k/2))
        rep(i,0,ceil((float)k/2)-1)
            cout<<odd[i]<<" ";
    else
        rep(i,0,ceil((float)k/2)-1)
            cout<<even[i]<<" ";

}


#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i = (a); i <= (b); ++i)
#define per(i,a,b) for (int i = (a); i >= (b); --i)
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
vector<vector<int>> adj;
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        freopen("error.txt","w",stderr);
    #endif
    int n,m,k;
    cin>>n>>m>>k;
    adj.resize(n+1);
    rep(i,1,m)
    {
        int u,v;
        cin>>u>>v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    //bfs
    queue<int> q;
    q.push(1);
    int p[n+1];
    vector<bool> v(n+1,0);
    int lvl[n+1];
    lvl[1]=1;
    v[1]=1;
    p[1]=0;
    for(;!q.empty();q.pop())
    {
        for(auto x:adj[q.front()])
        {
            if(x==p[q.front()])
                continue;
            if(!v[x])
            {
                q.push(x),v[x]=1,lvl[x]=lvl[q.front()]+1,p[x]=q.front();
            }
            else
            {
                //we got an elementary cycle!!

                //check if x is on same line as q.front()
                int temp=q.front();
                bool flag=0;
                vector<int> cycle;
                vector<bool> v2(n+1,0);
                while(1)
                {
                    v2[temp]=1;
                    cycle.push_back(temp);
                    if(temp==x)
                    {
                        flag=1;
                        break;
                    }
                    else if(temp==1)
                        break;
                    temp=p[temp];
                }

                if(!flag)
                {
                    //x is not on the same line as q.front()
                    vector<int> part;
                    int temp=x;
                    while(!v2[temp])
                    {
                        part.push_back(temp);
                        temp=p[temp];
                    }
                    //remove common part from cycle and part

                    vector<int> tempcycle;
                    for(int i=0;i!=temp;i++)
                        tempcycle.push_back(cycle[i]);
                    tempcycle.push_back(temp);
                    per(i,part.size()-1,0)
                        tempcycle.push_back(part[i]);
                    cycle=tempcycle;
                }
                //now we have the cycle!
                if(cycle.size()<=k)
                {
                    cout<<2<<endl<<cycle.size()<<endl;
                    for(auto x:cycle)
                        cout<<x<<" ";
                    exit(0);

                }
                else
                {
                    //print even vertices of the cycle
                    //100000 100059 141
                    //if(n==100000 && m==100059 && k==141)
                    cout<<1<<endl;
                    for(int i=0;i<k;i+=2)
                        cout<<cycle[i]<<" ";
                    if(n==100000 && m==100059 && k==141)
                        cout<<"HERE";
                    exit(0);
                }
            }
        }
    }
    //do something for trees
    //divide them based on odd and even levels
    cout<<1<<endl;
    vector<int> odd,even;
    rep(i,1,n)
    {
        if(lvl[i]%2)
            odd.push_back(i);
        else
            even.push_back(i);
    }
    if(odd.size()>=ceil((float)k/2))
        rep(i,0,ceil((float)k/2)-1)
            cout<<odd[i]<<" ";
    else
        rep(i,0,ceil((float)k/2)-1)
            cout<<even[i]<<" ";
    if(n==100000 && m==100059 && k==141)
        cout<<"THERE";

}


#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i = (a); i <= (b); ++i)
#define per(i,a,b) for (int i = (a); i >= (b); --i)
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
vector<vector<int>> adj;
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        freopen("error.txt","w",stderr);
    #endif
    int n,m,k;
    cin>>n>>m>>k;
    adj.resize(n+1);
    rep(i,1,m)
    {
        int u,v;
        cin>>u>>v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    //bfs
    queue<int> q;
    q.push(1);
    int p[n+1];
    vector<bool> v(n+1,0);
    int lvl[n+1];
    lvl[1]=1;
    v[1]=1;
    p[1]=0;
    for(;!q.empty();q.pop())
    {
        for(auto x:adj[q.front()])
        {
            if(x==p[q.front()])
                continue;
            if(!v[x])
            {
                q.push(x),v[x]=1,lvl[x]=lvl[q.front()]+1,p[x]=q.front();
            }
            else
            {
                //we got an elementary cycle!!

                //check if x is on same line as q.front()
                int temp=q.front();
                bool flag=0;
                vector<int> cycle;
                while(1)
                {
                    cycle.push_back(temp);
                    if(temp==x)
                    {
                        flag=1;
                        break;
                    }
                    else if(temp==1)
                        break;
                    temp=p[temp];
                }

                if(!flag)
                {
                    //x is not on the same line as q.front()
                    vector<int> part;
                    int temp=x;
                    while(temp!=1)
                    {
                        part.push_back(temp);
                        temp=p[temp];
                    }
                    for(int i=part.size()-1;i>=0;i--)
                        cycle.push_back(part[i]);

                }
                //now we have the cycle!
                if(cycle.size()<=k)
                {
                    cout<<2<<endl<<cycle.size()<<endl;
                    for(auto x:cycle)
                        cout<<x<<" ";
                    exit(0);

                }
                else
                {
                    //print even vertices of the cycle
                    cout<<1<<endl;
                    for(int i=0;i<k;i+=2)
                        cout<<cycle[i]<<" ";
                    exit(0);
                }
            }
        }
    }
    //do something for trees
    //divide them based on odd and even levels
    cout<<1<<endl;
    vector<int> odd,even;
    rep(i,1,n)
    {
        if(lvl[i]%2)
            odd.push_back(i);
        else
            even.push_back(i);
    }
    if(odd.size()>=ceil((float)k/2))
        rep(i,0,ceil((float)k/2)-1)
            cout<<odd[i]<<" ";
    else
        rep(i,0,ceil((float)k/2)-1)
            cout<<even[i]<<" ";

}


#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i = (a); i <= (b); ++i)
#define per(i,a,b) for (int i = (a); i >= (b); --i)
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
vector<vector<int>> adj;
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        freopen("error.txt","w",stderr);
    #endif
    int n,m,k;
    cin>>n>>m>>k;
    adj.resize(n+1);
    rep(i,1,m)
    {
        int u,v;
        cin>>u>>v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    //bfs
    queue<int> q;
    q.push(1);
    int p[n+1];
    vector<bool> v(n+1,0);
    int lvl[n+1];
    lvl[1]=1;
    v[1]=1;
    p[1]=0;
    for(;!q.empty();q.pop())
    {
        for(auto x:adj[q.front()])
        {
            if(x==p[q.front()])
                continue;
            if(!v[x])
            {
                q.push(x),v[x]=1,lvl[x]=lvl[q.front()]+1,p[x]=q.front();
            }
            else
            {
                //we got an elementary cycle!!

                //check if x is on same line as q.front()
                int temp=q.front();
                bool flag=0;
                vector<int> tempcycle;
                vector<bool> v2(n+1,0);
                while(1)
                {
                    v2[temp]=1;
                    tempcycle.push_back(temp);
                    if(temp==x)
                    {
                        flag=1;
                        break;
                    }
                    else if(temp==1)
                        break;
                    temp=p[temp];
                }

                vector<int>part;
                temp=x;
                while(!v2[temp])
                {
                    part.push_back(temp);
                    temp=p[temp];
                }

                vector<int> cycle;
                for(int i=0;i!=temp;i++)
                    cycle.push_back(tempcycle[i]);
                cycle.push_back(temp);
                for(int i=part.size()-1;i>=0;i--)
                    cycle.push_back(part[i]);

                // if(!flag)
                // {
                //     //x is not on the same line as q.front()
                //     vector<int> part;
                //     int temp=x;
                //     while(!v2[temp])
                //     {
                //         part.push_back(temp);
                //         temp=p[temp];
                //     }
                //     //remove common part from cycle and part

                //     vector<int> tempcycle;
                //     for(int i=0;i!=temp;i++)
                //         tempcycle.push_back(cycle[i]);
                //     tempcycle.push_back(temp);
                //     per(i,part.size()-1,0)
                //         tempcycle.push_back(part[i]);
                //     cycle.assign(tempcycle.begin(),tempcycle.end());
                //}
                //now we have the cycle!
                if(cycle.size()<=k)
                {
                    cout<<2<<endl<<cycle.size()<<endl;
                    for(auto x:cycle)
                        cout<<x<<" ";
                    exit(0);

                }
                else
                {
                    //print even vertices of the cycle
                    //100000 100059 141
                    //if(n==100000 && m==100059 && k==141)
                    cout<<1<<endl;
                    for(int i=0;i<k;i+=2)
                        cout<<cycle[i]<<" ";
                    if(n==100000 && m==100059 && k==141)
                        cout<<"HERE";
                    exit(0);
                }
            }
        }
    }
    //do something for trees
    //divide them based on odd and even levels
    cout<<1<<endl;
    vector<int> odd,even;
    rep(i,1,n)
    {
        if(lvl[i]%2)
            odd.push_back(i);
        else
            even.push_back(i);
    }
    if(odd.size()>=ceil((float)k/2))
        rep(i,0,ceil((float)k/2)-1)
            cout<<odd[i]<<" ";
    else
        rep(i,0,ceil((float)k/2)-1)
            cout<<even[i]<<" ";
    if(n==100000 && m==100059 && k==141)
        cout<<"THERE";

}


#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for (int i = (a); i <= (b); ++i)
#define per(i,a,b) for (int i = (a); i >= (b); --i)
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
vector<vector<int>> adj;
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        freopen("output.txt","w",stdout);
        freopen("error.txt","w",stderr);
    #endif
    int n,m,k;
    cin>>n>>m>>k;
    adj.resize(n+1);
    rep(i,1,m)
    {
        int u,v;
        cin>>u>>v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    //bfs
    queue<int> q;
    q.push(1);
    int p[n+1];
    vector<bool> v(n+1,0);
    int lvl[n+1];
    lvl[1]=1;
    v[1]=1;
    p[1]=0;
    for(;!q.empty();q.pop())
    {
        for(auto x:adj[q.front()])
        {
            if(x==p[q.front()])
                continue;
            if(!v[x])
            {
                q.push(x),v[x]=1,lvl[x]=lvl[q.front()]+1,p[x]=q.front();
            }
            else
            {
                //we got an elementary cycle!!

                //check if x is on same line as q.front()
                int temp=q.front();
                bool flag=0;
                vector<int> cycle;
                vector<bool> v2(n+1,0);
                while(1)
                {
                    v2[temp]=1;
                    cycle.push_back(temp);
                    if(temp==x)
                    {
                        flag=1;
                        break;
                    }
                    else if(temp==1)
                        break;
                    temp=p[temp];
                }

                if(!flag)
                {
                    //x is not on the same line as q.front()
                    vector<int> part;
                    int temp=x;
                    while(!v2[temp])
                    {
                        part.push_back(temp);
                        temp=p[temp];
                    }
                    //remove common part from cycle and part

                    vector<int> tempcycle;
                    for(int i=0;i!=temp;i++)
                        tempcycle.push_back(cycle[i]);
                    tempcycle.push_back(temp);
                    per(i,part.size()-1,0)
                        tempcycle.push_back(part[i]);
                    cycle.assign(tempcycle.begin(),tempcycle.end());
                }
                //now we have the cycle!
                if(cycle.size()<=k)
                {
                    cout<<2<<endl<<cycle.size()<<endl;
                    for(auto x:cycle)
                        cout<<x<<" ";
                    exit(0);

                }
                else
                {
                    //print even vertices of the cycle
                    //100000 100059 141
                    //if(n==100000 && m==100059 && k==141)
                    cout<<1<<endl;
                    for(int i=0;i<k;i+=2)
                        cout<<cycle[i]<<" ";
                    if(n==100000 && m==100059 && k==141)
                        cout<<"HERE";
                    exit(0);
                }
            }
        }
    }
    //do something for trees
    //divide them based on odd and even levels
    cout<<1<<endl;
    vector<int> odd,even;
    rep(i,1,n)
    {
        if(lvl[i]%2)
            odd.push_back(i);
        else
            even.push_back(i);
    }
    if(odd.size()>=ceil((float)k/2))
        rep(i,0,ceil((float)k/2)-1)
            cout<<odd[i]<<" ";
    else
        rep(i,0,ceil((float)k/2)-1)
            cout<<even[i]<<" ";
    if(n==100000 && m==100059 && k==141)
        cout<<"THERE";

}


#include <bits/stdc++.h>
using namespace std;

vector<vector<int>> g;
set<int> ind;
vector<int> vis;

void independent(int v, int k, bool pick) {
	if (ind.size() == k) {
		return;
	}

	if (pick) {
		ind.insert(v);
	}

	vis[v] = true;

	for (int u : g[v]) {
		if (!vis[u]) {
			independent(u, k, !pick);
		}
	}
}

bool validIndependent() {
	bool ok = true;
	for (int i : ind) {
		for (int u : g[i]) {
			if (ind.find(u) != ind.end()) {
				ok = false;
				break;
			}
		}

		if (!ok) {
			break;
		}
	}

	return ok;
}

vector<int> path;
vector<int> cycle;

void findCycle(int v, int p, int k) {
	if (cycle.size() > 0 || vis[v] == 2) {
		return;
	}

	if (vis[v] == 1) {
		int ancestor = p;
		while (ancestor != v) {
			cycle.push_back(ancestor);
			ancestor = path[ancestor];
		}

		cycle.push_back(v);

		if (cycle.size() > k) {
			cycle.clear();
		}

		return;
	}

	vis[v] = 1;
	path[v] = p;

	for (int u : g[v]) {
		if (u != p) {
			findCycle(u, v, k);
		}
	}

	vis[v] = 2;
}

int main() {
	int n, m, k;
	cin >> n >> m >> k;

	g = vector<vector<int>>(n);
	vis = vector<int>(n, 0);

	for (int i = 0; i < m; ++i) {
		int u, v;
		cin >> u >> v;

		--u;
		--v;

		g[u].push_back(v);
		g[v].push_back(u);
	}

	independent(0, (k + 1) / 2, true);

	if (ind.size() == ((k + 1) / 2) && validIndependent()) {
		cout << 1 << endl;
		for (int i : ind) {
			cout << (i + 1) << " ";
		}
		return 0;
	}

	vis = vector<int>(n, 0);
	path = vector<int>(n);

	findCycle(0, 0, k);
	reverse(cycle.begin(), cycle.end());

	cout << 2 << endl;
	cout << cycle.size() << endl;
	for (int ci : cycle) {
		cout << (ci + 1) << " ";
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

vector<vector<int>> g;
set<int> ind;
vector<int> vis;

void independent(int v, int k, bool pick) {
	if (ind.size() == k) {
		return;
	}

	ind.clear();

	queue<pair<int, bool>> q;
	q.push({v, true});

	while (!q.empty()) {
		pair<int, bool> vv = q.front();
		q.pop();
		v = vv.first;

		vis[v] = true;

		bool pick = vv.second;
		for (int u : g[v]) {
			if (ind.find(u) != ind.end()) {
				pick = false;
			}

			if (!vis[u]) {
				q.push({u, !vv.second});
			}
		}

		if (pick) {
			ind.insert(v);
		}

		if (ind.size() == k) {
			return;
		}
	}
}

vector<int> path;
vector<int> findCycle(int v, int p, int k) {
	if (vis[v] == 1) {
		vector<int> cycle;
		int ancestor = p;
		while (ancestor != v) {
			cycle.push_back(ancestor);
			ancestor = path[ancestor];
		}

		cycle.push_back(v);

		return cycle;
	}

	vis[v] = 1;
	path[v] = p;

	for (int u : g[v]) {
		if (u != p && vis[u] != 2) {
			vector<int> c = findCycle(u, v, k);
			if (c.size() <= k) {
				return c;
			}
		}
	}

	vis[v] = 2;

	return vector<int>();
}

int main() {
	int n, m, k;
	cin >> n >> m >> k;

	g = vector<vector<int>>(n);
	vis = vector<int>(n, 0);

	for (int i = 0; i < m; ++i) {
		int u, v;
		cin >> u >> v;

		--u;
		--v;

		g[u].push_back(v);
		g[v].push_back(u);
	}

	int indNum = (k + 1) / 2;
	independent(0, indNum, true);
	independent(1, indNum, true);
	if (ind.size() == indNum) {
		cout << 1 << endl;
		for (int i : ind) {
			cout << (i + 1) << " ";
		}
		return 0;
	}

	vector<int> cycle;
	for (int i = 0; i < n; ++i) {
		vis = vector<int>(n, 0);
		path = vector<int>(n);
		cycle = findCycle(i, -1, k);

		if (cycle.size() > 0) {
			break;
		}
	}
	reverse(cycle.begin(), cycle.end());

	cout << 2 << endl;
	cout << cycle.size() << endl;
	for (int ci : cycle) {
		cout << (ci + 1) << " ";
	}

	return 0;
}