Problem: Intersections of Crossing Path City are aligned to a grid. There are $N$ east-west streets which are numbered from 1 to $N$, from north to south. There are also $N$ north-south streets which are numbered from 1 to $N$, from west to east. Every pair of east-west and north-south streets has an intersection; therefore there are $N^2$ intersections which are numbered from 1 to $N^2$.

Surprisingly, all of the residents in the city are Ninja. To prevent outsiders from knowing their locations, the numbering of intersections is shuffled.

You know the connections between the intersections and try to deduce their positions from the information. If there are more than one possible set of positions, you can output any of them.



Input

The input consists of a single test case formatted as follows.


$N$
$a_1$ $b_1$
...
$a_{2N^2−2N}$ $\;$ $b_{2N^2−2N}$


The first line consists of an integer $N$ ($2 \leq N \leq 100$). The following $2N^2 - 2N$ lines represent connections between intersections. The ($i+1$)-th line consists of two integers $a_i$ and $b_i$ ($1 \leq a_i, b_i \leq N^2, a_i \ne b_i$), which represent that the $a_i$-th and $b_i$-th intersections are adjacent. More precisely, let's denote by ($r, c$) the intersection of the $r$-th east-west street and the $c$-th north-south street. If the intersection number of ($r,c$) is $a_i$ for some $r$ and $c$, then the intersection number of either ($r-1, c$), ($r+1, c$), ($r, c-1$) or ($r, c+1$) must be $b_i$. All inputs of adjacencies are different, i.e., ($a_i, b_i$) $\ne$ ($a_j, b_j$) and ($a_i, b_i$) $\ne$ ($b_j, a_j$) for all $1 \leq i < j \leq 2N^2-2N$. This means that you are given information of all adjacencies on the grid.

The input is guaranteed to describe a valid map.

Output

Print a possible set of positions of the intersections. More precisely, the output consists of $N$ lines each of which has space-separated $N$ integers. The $c$-th integer of the $r$-th line should be the intersection number of ($r, c$).

If there are more than one possible set of positions, you can output any of them.

Examples

Input

3
1 2
4 7
8 6
2 3
8 9
5 3
4 6
5 6
7 8
1 4
2 6
5 9


Output

7 4 1
8 6 2
9 5 3


Input

4
12 1
3 8
10 7
13 14
8 2
9 12
6 14
11 3
3 13
1 10
11 15
4 15
4 9
14 10
5 7
2 5
6 1
14 5
16 11
15 6
15 13
9 6
16 4
13 2


Output

8 2 5 7
3 13 14 10
11 15 6 1
16 4 9 12

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using PII = pair<ll, ll>;
#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
template<typename T> void chmin(T &a, const T &b) { a = min(a, b); }
template<typename T> void chmax(T &a, const T &b) { a = max(a, b); }
struct FastIO {FastIO() { cin.tie(0); ios::sync_with_stdio(0); }}fastiofastio;
#ifdef DEBUG_ 
#include "../program_contest_library/memo/dump.hpp"
#else
#define dump(...)
#endif
const ll INF = 1LL<<60;

int main(void) {
    ll n;
    cin >> n;
    vector<ll> a(2*n*n-2*n), b(2*n*n-2*n), deg(n*n);
    vector<vector<ll>> g(n*n);
    REP(i, 2*n*n-2*n) {
        cin >> a[i] >> b[i];
        a[i]--, b[i]--;
        deg[a[i]]++;
        deg[b[i]]++;
        g[a[i]].push_back(b[i]);
        g[b[i]].push_back(a[i]);
    }

    // dump(g);

    vector<ll> v1, v2, v3;
    REP(i, n*n) {
        if(deg[i] == 2) v1.push_back(i);
        else if(deg[i] == 3) v2.push_back(i);
        else v3.push_back(i);
    }

    ll dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
    auto check = [&](vector<vector<ll>> ans) {
        REP(i, n) REP(j, n) {
            REP(k, 4) {
                ll nx = j + dx[k], ny = i + dy[k];
                if(0 > nx || nx >= n || 0 > ny || ny >= n) continue;
                bool flag = false;
                for(auto to: g[ans[i][j]]) if(ans[ny][nx] == to) flag = true;
                if(!flag) {
                    dump(i, j, ny, nx);
                    return false;
                }
            }
        }
        return true;
    };

    vector<bool> used(n*n);
    vector<vector<ll>> ans(n, vector<ll>(n));

    if(n == 2) {
        sort(ALL(v1));
        do {
            ll idx = 0;
            REP(i, n) REP(j, n) ans[i][j] = v1[idx++];
            if(check(ans)) {
                REP(i, n) REP(j, n) cout << ans[i][j]+1 << (j==n-1?'\n':' ');
                cout << flush;
                exit(0);
            }
        } while(next_permutation(ALL(v1)));
        assert(false);
    }

    auto solve = [&] {
        FOR(i, 2, n-1) {
            if(ans[0][i-1] == -1) return;
            for(auto to: g[ans[0][i-1]]) if(deg[to] == 3 && !used[to]) {
                ans[0][i] = to;
                used[to] = true;
            }
        }
        FOR(i, 1, n-1) {
            if(ans[i-1][0] == -1) return;
            for(auto to: g[ans[i-1][0]]) if(deg[to] == 3 && !used[to]) {
                ans[i][0] = to;
                used[to] = true;
            }
        }
        FOR(i, 1, n-1) {
            if(ans[n-1][i-1] == -1) return;
            for(auto to: g[ans[n-1][i-1]]) if(deg[to] == 3 && !used[to]) {
                ans[n-1][i] = to;
                used[to] = true;
            }
        }
        FOR(i, 1, n-1) {
            // if(i == 2) {
            //     dump(g[3968]);
            //     dump(i, ans[i-1][n-1]);
            //     dump(ans[0]);
            //     dump(ans[1]);
            // }
            if(ans[i-1][n-1] == -1) return;
            for(auto to: g[ans[i-1][n-1]]) {
                if(deg[to] == 3 && !used[to]) {
                    ans[i][n-1] = to;
                    used[to] = true;
                }
            }
        }
        // dump("hen");
        // 中央
        FOR(i, 1, n-1) FOR(j, 1, n-1) {
            // ans[i][j] の値は ans[i-1][j] と ans[i][j-1] に隣接するやつで一意に決まる
            set<ll> st;
            if(ans[i-1][j]==-1 || ans[i][j-1]==-1) return;
            for(auto to1: g[ans[i-1][j]]) st.insert(to1);
            for(auto to2: g[ans[i][j-1]]) {
                if(st.find(to2) != st.end() && !used[to2]) {
                    ans[i][j] = to2;
                    used[to2] = true;
                }
            }
        }
        // dump("tyuou");
        // dump(ans);
        if(check(ans)) {
            REP(i, n) REP(j, n) cout << ans[i][j]+1 << (j==n-1?'\n':' ');
            cout << flush;
            exit(0);
        }
    };

    sort(ALL(v1));
    do {
        dump(v1);
        REP(i, n) REP(j, n) ans[i][j] = -1;
        used.assign(n*n, false);
        ans[0][0] = v1[0]; used[v1[0]] = true;
        ans[0][n-1] = v1[1]; used[v1[1]] = true;
        ans[n-1][0] = v1[2]; used[v1[2]] = true;
        ans[n-1][n-1] = v1[3]; used[v1[3]] = true;
        ans[0][1] = g[ans[0][0]][0]; used[ans[0][1]] = true;
        solve();

        REP(i, n) REP(j, n) ans[i][j] = -1;
        used.assign(n*n, false);
        ans[0][0] = v1[0]; used[v1[0]] = true;
        ans[0][n-1] = v1[1]; used[v1[1]] = true;
        ans[n-1][0] = v1[2]; used[v1[2]] = true;
        ans[n-1][n-1] = v1[3]; used[v1[3]] = true;
        ans[0][1] = g[ans[0][0]][1]; used[ans[0][1]] = true;
        solve();
    } while(next_permutation(ALL(v1)));
    
    return 0;
}