A football league has recently begun in Beautiful land. There are $$$n$$$ teams participating in the league. Let's enumerate them with integers from $$$1$$$ to $$$n$$$.There will be played exactly $$$\frac{n(n-1)}{2}$$$ matches: each team will play against all other teams exactly once. In each match, there is always a winner and loser and there is no draw.After all matches are played, the organizers will count the number of beautiful triples. Let's call a triple of three teams $$$(A, B, C)$$$ beautiful if a team $$$A$$$ win against a team $$$B$$$, a team $$$B$$$ win against a team $$$C$$$ and a team $$$C$$$ win against a team $$$A$$$. We look only to a triples of different teams and the order of teams in the triple is important.The beauty of the league is the number of beautiful triples.At the moment, $$$m$$$ matches were played and their results are known.What is the maximum beauty of the league that can be, after playing all remaining matches? Also find a possible results for all remaining $$$\frac{n(n-1)}{2} - m$$$ matches, so that the league has this maximum beauty.

The first line contains two integers $$$n, m$$$ ($$$3 \leq n \leq 50, 0 \leq m \leq \frac{n(n-1)}{2}$$$) — the number of teams in the football league and the number of matches that were played. Each of $$$m$$$ following lines contains two integers $$$u$$$ and $$$v$$$ ($$$1 \leq u, v \leq n$$$, $$$u \neq v$$$) denoting that the $$$u$$$-th team won against the $$$v$$$-th team. It is guaranteed that each unordered pair of teams appears at most once.

Print $$$n$$$ lines, each line having a string of exactly $$$n$$$ characters. Each character must be either $$$0$$$ or $$$1$$$. Let $$$a_{ij}$$$ be the $$$j$$$-th number in the $$$i$$$-th line. For all $$$1 \leq i \leq n$$$ it should be true, that $$$a_{ii} = 0$$$. For all pairs of teams $$$i \neq j$$$ the number $$$a_{ij}$$$ indicates the result of the match between the $$$i$$$-th team and the $$$j$$$-th team:   If $$$a_{ij}$$$ is $$$1$$$, the $$$i$$$-th team wins against the $$$j$$$-th team;  Otherwise the $$$j$$$-th team wins against the $$$i$$$-th team;  Also, it should be true, that $$$a_{ij} + a_{ji} = 1$$$.  Also note that the results of the $$$m$$$ matches that were already played cannot be changed in your league. The beauty of the league in the output should be maximum possible. If there are multiple possible answers with maximum beauty, you can print any of them.

NoteThe beauty of league in the first test case is equal to $$$3$$$ because there exists three beautiful triples: $$$(1, 2, 3)$$$, $$$(2, 3, 1)$$$, $$$(3, 1, 2)$$$.The beauty of league in the second test is equal to $$$6$$$ because there exists six beautiful triples: $$$(1, 2, 4)$$$, $$$(2, 4, 1)$$$, $$$(4, 1, 2)$$$, $$$(2, 4, 3)$$$, $$$(4, 3, 2)$$$, $$$(3, 2, 4)$$$.

/+ dub.sdl:
    name "X"
    dependency "dunkelheit" version="1.0.1"
+/

import std.stdio, std.algorithm, std.range, std.conv;
// import dkh.foundation, dkh.scanner, dkh.graph.mincostflow;

int main() {
    Scanner sc = new Scanner(stdin);
    scope(exit) assert(!sc.hasNext);

    int n, m;
    sc.read(n, m);
    int ec = n * (n - 1) / 2;
    int v = ec + n + 2;
    int sv = ec + n, tv = sv + 1;
    struct E {
        int to, rev, cap, dist;
    }
    E[][] g = new E[][](v);
    void addEdge(int from, int to, int cap, int dist) {
        g[from] ~= E(to, g[to].length.to!int, cap, dist);
        g[to] ~= E(from, g[from].length.to!int-1, 0, -dist);
    }
    int[][] def = new int[][](n, n);
    foreach (i; 0..m) {
        int a, b;
        sc.read(a, b); a--; b--;
        def[a][b] = 1;
        def[b][a] = -1;
    }
    int id = 0;
    foreach (i; 0..n) {
        foreach (j; i + 1..n) {
            addEdge(sv, id, 1, 0);
            if (def[i][j] != -1) {
                addEdge(id, ec + i, 1, 0);
            }
            if (def[j][i] != -1) {
                addEdge(id, ec + j, 1, 0);
            }
            id++;
        }
    }
    foreach (i; 0..n) {
        foreach (j; 1..n+1) {
            addEdge(ec + i, tv, 1, j - 1);
        }
    }
    auto mcfInfo = minCostFlow!(int, int, 0)(g, sv, tv, false);
    mcfInfo.manyFlow(10^^9);

    int[][] ans = new int[][](n, n);
    id = 0;
    foreach (i; 0..n) {
        foreach (j; i + 1..n) {
            foreach (e; g[id]) {
                if (e.to < ec || ec + n <= e.to) continue;
                if (e.cap) continue;
                if (e.to == ec + i) ans[i][j] = 1;
                else ans[j][i] = 1;
                break;
            }
            id++;
        }
    }

    foreach (i; 0..n) {
        foreach (j; 0..n) {
            write(ans[i][j]);
        }
        writeln;
    }
    return 0;
}
/* IMPORT /Users/yosupo/Programs/dunkelheit/source/dkh/foundation.d */

// module dkh.foundation;

static if (__VERSION__ <= 2070) {
    /*
    Copied by https://github.com/dlang/phobos/blob/master/std/algorithm/iteration.d
    Copyright: Andrei Alexandrescu 2008-.
    License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
    */
    template fold(fun...) if (fun.length >= 1) {
        auto fold(R, S...)(R r, S seed) {
            import std.algorithm : reduce;
            static if (S.length < 2) {
                return reduce!fun(seed, r);
            } else {
                import std.typecons : tuple;
                return reduce!fun(tuple(seed), r);
            }
        }
    }

}
/* IMPORT /Users/yosupo/Programs/dunkelheit/source/dkh/container/deque.d */
// module dkh.container.deque;

struct DequePayload(T) {
    import core.exception : RangeError;

    private T* _data;
    private uint start, len, cap;

    @property bool empty() const { return len == 0; }
    @property size_t length() const { return len; }
    alias opDollar = length;

    ref inout(T) opIndex(size_t i) inout {
        version(assert) if (len <= i) throw new RangeError();
        if (start + i < cap) return _data[start + i];
        else return _data[start + i - cap];
    }
    ref inout(T) front() inout { return this[0]; }
    ref inout(T) back() inout { return this[$-1]; }

    void reserve(size_t newCap) {
        import core.memory : GC;
        import std.algorithm : max;
        import std.conv : to;
        if (newCap <= cap) return;
        T* newData = cast(T*)GC.malloc(newCap * T.sizeof);
        foreach (i; 0..length) {
            newData[i] = this[i];
        }
        _data = newData; start = 0; cap = newCap.to!uint;
    }
    void clear() {
        start = len = 0;
    }
    import std.algorithm : max;
    void insertFront(T item) {
        if (len == cap) reserve(max(cap * 2, 4));
        if (start == 0) start += cap;
        start--; len++;
        this[0] = item;
    }
    void insertBack(T item) {
        if (len == cap) reserve(max(cap * 2, 4));
        len++;
        this[len-1] = item;
    }
    void removeFront() {
        assert(!empty, "Deque.removeFront: Deque is empty");
        start++; len--;
        if (start == cap) start = 0;
    }
    void removeBack() {
        assert(!empty, "Deque.removeBack: Deque is empty");
        len--;
    }
}

struct Deque(T, bool mayNull = true) {
    import core.exception : RangeError;
    import std.range : ElementType, isInputRange;
    import std.traits : isImplicitlyConvertible;

    alias Payload = DequePayload!T;
    Payload* _p;

    static if (!mayNull) @disable this();

    this(U)(U[] values...) if (isImplicitlyConvertible!(U, T)) {
        _p = new Payload();
        foreach (v; values) {
            insertBack(v);
        }
    }

    this(Range)(Range r)
    if (isInputRange!Range &&
    isImplicitlyConvertible!(ElementType!Range, T) &&
    !is(Range == T[])) {
        _p = new Payload();
        foreach (v; r) {
            insertBack(v);
        }
    }
    private this(Payload* p) { _p = p; }
    static Deque make() { return Deque(new Payload()); }

    private bool havePayload() const { return (!mayNull || _p); }
    @property bool empty() const { return (!havePayload || _p.empty); }
    @property size_t length() const { return (havePayload ? _p.length : 0); }
    alias opDollar = length;

    ref inout(T) opIndex(size_t i) inout {
        assert(!empty, "Deque.opIndex: Deque is empty");
        return (*_p)[i];
    }
    ref inout(T) front() inout { return this[0]; }
    ref inout(T) back() inout { return this[$-1]; }

    void clear() { if (_p) _p.clear(); }

    void insertFront(T item) {
        if (mayNull && !_p) _p = new Payload();
        _p.insertFront(item);
    }
    void insertBack(T item) {
        if (mayNull && !_p) _p = new Payload();
        _p.insertBack(item);
    }
    alias opOpAssign(string op : "~") = insertBack;
    alias stableInsertBack = insertBack;

    void removeFront() {
        assert(!mayNull || _p, "Deque.removeFront: Deque is empty");
        _p.removeFront();
    }
    void removeBack() {
        assert(!mayNull || _p, "Deque.removeBack: Deque is empty");
        _p.removeBack();
    }
    alias stableRemoveBack = removeBack;

    alias Range = RangeT!(DequePayload!T);
    alias ConstRange = RangeT!(const DequePayload!T);
    alias ImmutableRange = RangeT!(immutable DequePayload!T);

    size_t[2] opSlice(size_t dim : 0)(size_t start, size_t end) const {
        assert(start <= end && end <= length);
        return [start, end];
    }
    Range opIndex(size_t[2] rng) { return Range(_p, rng[0], rng[1]); }
    ConstRange opIndex(size_t[2] rng) const { return ConstRange(_p, rng[0], rng[1]); }
    ImmutableRange opIndex(size_t[2] rng) immutable { return ImmutableRange(_p, rng[0], rng[1]); }
    auto opIndex() inout { return this[0..$]; }

    static struct RangeT(QualifiedPayload) {
        alias A = QualifiedPayload;
        import std.traits : CopyTypeQualifiers;
        alias E = CopyTypeQualifiers!(A, T);
        A *p;
        size_t l, r;

        @property bool empty() const { return r <= l; }
        @property size_t length() const { return r - l; }
        alias opDollar = length;

        @property auto save() { return this; }

        ref inout(E) opIndex(size_t i) inout {
            version(assert) if (empty) throw new RangeError();
            return (*p)[l+i];
        }
        @property ref inout(E) front() inout { return this[0]; }
        @property ref inout(E) back() inout { return this[$-1]; }

        void popFront() {
            version(assert) if (empty) throw new RangeError();
            l++;
        }
        void popBack() {
            version(assert) if (empty) throw new RangeError();
            r--;
        }

        size_t[2] opSlice(size_t dim : 0)(size_t start, size_t end) const {
            assert(start <= end && end <= length);
            return [start, end];
        }
        auto opIndex(size_t[2] rng) { return RangeT(p, l+rng[0], l+rng[1]); }
        auto opIndex(size_t[2] rng) const { return RangeT!(const A)(p, l+rng[0], l+rng[1]); }
        auto opIndex(size_t[2] rng) immutable { return RangeT!(immutable A)(p, l+rng[0], l+rng[1]); }
        auto opIndex() inout { return this[0..$]; }
    }
}

/* IMPORT /Users/yosupo/Programs/dunkelheit/source/dkh/container/radixheap.d */
// module dkh.container.radixheap;

// import dkh.container.stackpayload;

import std.functional : unaryFun;
import std.traits : isSigned, isUnsigned;

template RadixHeap(T, alias pred = "a") {
    alias _pred = unaryFun!pred;
    alias K = typeof(_pred(T()));

    static if (isUnsigned!K) {

        struct RadixHeap {
            static struct Payload {
                StackPayload!T[K.sizeof*8+1] v;
                size_t len;
                K last;

                private static int bsr1(K x) {
                    import core.bitop : bsr;
                    return (x == 0) ? 0 : bsr(x)+1;
                }
                private void assign(T item) {
                    K key = _pred(item);
                    assert(last <= key);
                    v[bsr1(key^last)] ~= item;
                }
                private void pull() {
                    import std.range, std.algorithm;
                    if (v[0].length) return;
                    auto i = iota(K.sizeof*8+1).find!(a => v[a].length).front;

                    last = v[i].data[].map!_pred.reduce!min;
                    v[i].data.each!(a => assign(a));
                    v[i].clear();
                }

                void insert(T item) {
                    len++;
                    assign(item);
                }
                T front() {
                    pull();
                    return v[0].back;
                }
                void removeFront() {
                    pull();
                    len--;
                    v[0].removeBack();
                }
            }
            Payload* p;

            @property bool empty() const { return (!p || p.len == 0); }
            @property size_t length() const { return (!p ? 0 : p.len); }
            alias opDollar = length;

            T front() {
                assert(!empty, "RadixHeap.front: heap is empty");
                return p.front;
            }
            void insert(T item) {
                if (!p) p = new Payload();
                p.insert(item);
            }
            void removeFront() {
                assert(!empty, "RadixHeap.removeFront: heap is empty");
                p.removeFront();
            }
        }
    } else static if (isSigned!K) {

        import std.traits : Unsigned;
        static Unsigned!K pred2(in T item) {
            return _pred(item) ^ (K(1) << (K.sizeof*8 - 1));
        }
        alias RadixHeap = RadixHeap!(T, pred2);
    } else {
        static assert(false);
    }
}

/* IMPORT /Users/yosupo/Programs/dunkelheit/source/dkh/graph/mincostflow.d */
// module dkh.graph.mincostflow;

// import dkh.container.deque;

struct MinCostFlowInfo(C, D, D EPS, T) {
    T g;
    int s, t;
    C nc, capFlow;
    D nd, flow;
    D[] dual;
    private int[] pv, pe;
    this(T g, int s, int t) {
        this.g = g;
        this.s = s;
        this.t = t;
        flow = D(0);
        dual = new D[g.length]; dual[] = D(0);
        pv = new int[g.length];
        pe = new int[g.length];
    }
}

MinCostFlowInfo!(C, D, EPS, T) minCostFlow(C, D, D EPS, T)(T g, int s, int t, bool neg = false) {
    assert(s != t);
    auto mcfInfo = MinCostFlowInfo!(C, D, EPS, T)(g, s, t);
    mcfInfo.dualRef(neg);
    return mcfInfo;
}

C singleFlow(C, D, alias EPS, T)(ref MinCostFlowInfo!(C, D, EPS, T) mcfInfo, C c) {
    import std.algorithm;
    with (mcfInfo) {
        if (nd == D.max) return nc;
        c = min(c, nc);
        for (int v = t; v != s; v = pv[v]) {
            g[pv[v]][pe[v]].cap -= c;
            g[v][g[pv[v]][pe[v]].rev].cap += c;
        }
        capFlow += c;
        flow += c * nd;
        nc -= c;
        if (!nc) dualRef(mcfInfo, false);
    }
    return c;
}

void manyFlow(C, D, alias EPS, T)(ref MinCostFlowInfo!(C, D, EPS, T) mcfInfo, C c) {
    with (mcfInfo) {
        while (c) {
            C f = singleFlow(mcfInfo, c);
            if (!f) break;
            c -= f;
        }
    }
}

// import dkh.container.stackpayload;
// import dkh.container.radixheap;

void dualRef(bool neg, C, D, alias EPS, T)(ref MinCostFlowInfo!(C, D, EPS, T) mcfInfo) {
    import std.conv : to;
    import std.traits : isIntegral;
    import std.typecons;
    import std.container;
    import std.algorithm;
    alias P = Tuple!(int, "to", D, "dist");

    with(mcfInfo) {
        int n = g.length.to!int;
        D[] dist = new D[n]; dist[] = D.max;
        pv[] = -1; pe[] = -1;
        StackPayload!int refV;
        auto que = (){
            static if (!neg) {
                static if (isIntegral!D) {
                    return RadixHeap!(P, "a.dist")();
                } else {
                    return heapify!"a.dist>b.dist"(make!(Array!P));
                }
            } else {
                return Deque!P();
            }
        }();
        void insert(P p) {
            static if (!neg) {
                que.insert(p);
            } else {
                que.insertBack(p);
            }
        }
        P pop() {
            P p;
            static if (!neg) {
                p = que.front();
                que.removeFront();
            } else {
                p = que.back();
                que.removeBack();
            }
            return p;
        }
        insert(P(s, D(0)));
        dist[s] = D(0);
        while (!que.empty) {
            P p = pop();
            int v = p.to;
            if (dist[v] < p.dist) continue;
            if (!neg) {
                if (v == t) break;
                refV ~= v;
            }
            foreach (int i, e; g[v]) {
                D ed = e.dist + dual[v] - dual[e.to];
                if (e.cap && dist[e.to] > dist[v] + ed + EPS) {
                    dist[e.to] = dist[v] + ed;
                    pv[e.to] = v; pe[e.to] = i;
                    insert(P(e.to, dist[e.to]));
                }
            }
        }
        if (dist[t] == D.max) {
            nd = D.max;
            nc = 0;
            return;
        }
        static if (!neg) {
            foreach (v; refV.data) {
                if (dist[v] >= dist[t]) continue;
                dual[v] += dist[v]-dist[t];
            }
        } else {
            for (int v = 0; v < n; v++) {
                if (dist[v] == D.max) dual[v] = D.max;
                else dual[v] += dist[v];
            }
        }

        nd = dual[t]-dual[s];
        nc = C.max;
        for (int v = t; v != s; v = pv[v]) {
            nc = min(nc, g[pv[v]][pe[v]].cap);
        }
    }
}

void dualRef(C, D, alias EPS, T)(ref MinCostFlowInfo!(C, D, EPS, T) mcfInfo, bool neg) {
    if (neg == false) {
        dualRef!false(mcfInfo);
    } else {
        dualRef!true(mcfInfo);
    }
}

/* IMPORT /Users/yosupo/Programs/dunkelheit/source/dkh/container/stackpayload.d */
// module dkh.container.stackpayload;

struct StackPayload(T, size_t MINCAP = 4) if (MINCAP >= 1) {
    import core.exception : RangeError;

    private T* _data;
    private uint len, cap;

    @property bool empty() const { return len == 0; }
    @property size_t length() const { return len; }
    alias opDollar = length;

    inout(T)[] data() inout { return (_data) ? _data[0..len] : null; }

    ref inout(T) opIndex(size_t i) inout {
        version(assert) if (len <= i) throw new RangeError();
        return _data[i];
    }
    ref inout(T) front() inout { return this[0]; }
    ref inout(T) back() inout { return this[$-1]; }

    void reserve(size_t newCap) {
        import core.memory : GC;
        import core.stdc.string : memcpy;
        import std.conv : to;
        if (newCap <= cap) return;
        void* newData = GC.malloc(newCap * T.sizeof);
        cap = newCap.to!uint;
        if (len) memcpy(newData, _data, len * T.sizeof);
        _data = cast(T*)(newData);
    }
    void free() {
        import core.memory : GC;
        GC.free(_data);
    }

    void clear() {
        len = 0;
    }

    void insertBack(T item) {
        import std.algorithm : max;
        if (len == cap) reserve(max(cap * 2, MINCAP));
        _data[len++] = item;
    }
    alias opOpAssign(string op : "~") = insertBack;
    void removeBack() {
        assert(!empty, "StackPayload.removeBack: Stack is empty");
        len--;
    }
}

/* IMPORT /Users/yosupo/Programs/dunkelheit/source/dkh/scanner.d */
// module dkh.scanner;

// import dkh.container.stackpayload;

class Scanner {
    import std.stdio : File;
    import std.conv : to;
    import std.range : front, popFront, array, ElementType;
    import std.array : split;
    import std.traits : isSomeChar, isStaticArray, isArray;
    import std.algorithm : map;
    private File f;

    this(File f) {
        this.f = f;
    }
    private char[512] lineBuf;
    private char[] line;
    private bool succW() {
        import std.range.primitives : empty, front, popFront;
        import std.ascii : isWhite;
        while (!line.empty && line.front.isWhite) {
            line.popFront;
        }
        return !line.empty;
    }
    private bool succ() {
        import std.range.primitives : empty, front, popFront;
        import std.ascii : isWhite;
        while (true) {
            while (!line.empty && line.front.isWhite) {
                line.popFront;
            }
            if (!line.empty) break;
            line = lineBuf[];
            f.readln(line);
            if (!line.length) return false;
        }
        return true;
    }

    private bool readSingle(T)(ref T x) {
        import std.algorithm : findSplitBefore;
        import std.string : strip;
        import std.conv : parse;
        if (!succ()) return false;
        static if (isArray!T) {
            alias E = ElementType!T;
            static if (isSomeChar!E) {

                auto r = line.findSplitBefore(" ");
                x = r[0].strip.dup;
                line = r[1];
            } else static if (isStaticArray!T) {
                foreach (i; 0..T.length) {
                    assert(succW());
                    x[i] = line.parse!E;
                }
            } else {
                StackPayload!E buf;
                while (succW()) {
                    buf ~= line.parse!E;
                }
                x = buf.data;
            }
        } else {
            x = line.parse!T;
        }
        return true;
    }

    int unsafeRead(T, Args...)(ref T x, auto ref Args args) {
        if (!readSingle(x)) return 0;
        static if (args.length == 0) {
            return 1;
        } else {
            return 1 + read(args);
        }
    }

    void read(Args...)(auto ref Args args) {
        import std.exception : enforce;
        static if (args.length != 0) {
            enforce(readSingle(args[0]));
            read(args[1..$]);
        }
    }

    bool hasNext() {
        return succ();
    }
}

/*
This source code generated by dunkelheit and include dunkelheit's source code.
dunkelheit's Copyright: Copyright (c) 2016- Kohei Morita. (https://github.com/yosupo06/dunkelheit)
dunkelheit's License: MIT License(https://github.com/yosupo06/dunkelheit/blob/master/LICENSE.txt)
*/

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

class MinCostFlow(Capa, Cost, Capa CAPA_EPS = 0) {
  int n, m;
  int[][] g;
  int[] as, bs;
  Capa[] capa;
  Cost[] cost, pot;
  Capa tof;
  Cost toc;
  this(int n) {
    this.n = n; m = 0; g = new int[][n]; as = []; bs = []; capa = []; cost = [];
  }
  int addEdge(int u, int v, Capa w, Cost c) {
    debug {
      writeln("addEdge ", u, " ", v, " ", w, " ", c);
    }
    const i = m;
    g[u] ~= m; as ~= u; bs ~= v; capa ~= w; cost ~= c; ++m;
    g[v] ~= m; as ~= v; bs ~= u; capa ~= 0; cost ~= -c; ++m;
    return i;
  }
  bool solve(int source, int sink, Capa flow) {
    pot = new Cost[n];
    pot[] = 0;
    for (; ; ) {
      bool cont;
      foreach (u; 0 .. n) foreach (i; g[u]) if (capa[i] > CAPA_EPS) {
        const v = bs[i];
        if (pot[v] > pot[u] + cost[i]) {
          pot[v] = pot[u] + cost[i];
          cont = true;
        }
      }
      if (!cont) break;
    }
    auto dist = new Cost[n];
    auto prei = new int[n];
    auto on = new bool[n];
    for (tof = 0, toc = 0; tof + CAPA_EPS < flow; ) {
      DList!int que;
      dist[] = -1;
      prei[] = -1;
      on[] = false;
      dist[source] = 0;
      prei[source] = -2;
      on[source] = true;
      que ~= source;
      for (; !que.empty(); ) {
        const u = que.front;
        que.removeFront;
        on[u] = false;
        foreach (i; g[u]) if (capa[i] > CAPA_EPS) {
          const v = bs[i];
          const cc = dist[u] + cost[i] + pot[u] - pot[v];
          if (prei[v] == -1 || dist[v] > cc) {
            dist[v] = cc;
            prei[v] = i;
            if (!on[v]) {
              on[v] = true;
              que ~= v;
            }
          }
        }
      }
      if (prei[sink] == -1) return false;
      Capa f = flow - tof;
      for (int v = sink; v != source; ) {
        const i = prei[v];
        if (f > capa[i]) f = capa[i];
        v = as[i];
      }
      for (int v = sink; v != source; ) {
        const i = prei[v];
        capa[i] -= f; capa[i ^ 1] += f;
        v = as[i];
      }
      tof += f;
      toc += f * (dist[sink] - pot[source] + pot[sink]);
      pot[] += dist[];
    }
    return true;
  }
}

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      const M = readInt();
      auto U = new int[M];
      auto V = new int[M];
      foreach (i; 0 .. M) {
        U[i] = readInt() - 1;
        V[i] = readInt() - 1;
      }

      auto adj = new int[][](N, N);
      foreach (u; 0 .. N) {
        adj[u][] = -1;
      }
      foreach (i; 0 .. M) {
        adj[U[i]][V[i]] = 1;
        adj[V[i]][U[i]] = 0;
      }
      debug {
        writeln("adj = ", adj);
      }

      auto mcf = new MinCostFlow!(int, long)(2 + N + N * (N - 1) / 2);
      auto ids = new int[][](N, N);
      foreach (u; 0 .. N) {
        // -d (N - 1 - d)
        foreach (d; 0 .. N - 1) {
          const diff = (-(d + 1) * (N - 1 - (d + 1))) - (-d * (N - 1 - d));
          mcf.addEdge(0, 2 + u, 1, diff);
          debug {
            writeln(u, " ", d, ": ", diff);
          }
        }
      }
      foreach (x; 2 + N .. 2 + N + N * (N - 1) / 2) {
        mcf.addEdge(x, 1, 1, 0);
      }
      foreach (u; 0 .. N) {
        ids[u][] = -1;
      }
      {
        int x = 2 + N;
        foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
          if (adj[u][v] != 0) ids[u][v] = mcf.addEdge(2 + u, x, 1, 0);
          if (adj[v][u] != 0) ids[v][u] = mcf.addEdge(2 + v, x, 1, 0);
          ++x;
        }
        assert(x == 2 + N + N * (N - 1) / 2);
      }
      const res = mcf.solve(0, 1, N * (N - 1) / 2);
      debug {
        writeln("tof = ", mcf.tof, ", toc = ", mcf.toc);
      }
      assert(res);

      auto ans = new int[][](N, N);
      foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
        if (ids[u][v] != -1 && mcf.capa[ids[u][v]] == 0) ans[u][v] = 1;
        if (ids[v][u] != -1 && mcf.capa[ids[v][u]] == 0) ans[v][u] = 1;
        assert(ans[u][v] + ans[v][u] == 1);
      }
      foreach (u; 0 .. N) {
        foreach (v; 0 .. N) {
          write(ans[u][v]);
        }
        writeln();
      }
    }
  } catch (EOFException e) {
  }
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

class MinCostFlow(wint, cint) {
  int n, m;
  int[][] g;
  int[] zu;
  wint[] capa0, capa, ex;
  cint[] cost;
  real[] pot;
  bool[] vis;
  int[] itr, lev;
  this(int n) {
    this.n = n; m = 0; g = new int[][n]; zu = null; capa = null; cost = null;
    ex = new wint[n]; pot = new real[n]; pot[] = 0; vis = new bool[n]; itr = new int[n]; lev = new int[n];
  }
  int addEdge(int u, int v, wint w, cint c) {
    debug {
      writeln("addEdge ", u, " ", v, " ", w, " ", c);
    }
    const i = m;
    g[u] ~= m; zu ~= v; capa0 ~= w; capa ~= w; cost ~= +c; ++m;
    g[v] ~= m; zu ~= u; capa0 ~= 0; capa ~= 0; cost ~= -c; ++m;
    return i;
  }
  wint augment(int u, int t, wint f) {
    if (u == t) return f;
    foreach (i; g[u][itr[u] .. $]) {
      if (capa[i] > 0 && lev[u] < lev[zu[i]]) {
        wint g = augment(zu[i], t, min(f, capa[i]));
        if (g > 0) {
          capa[i] -= g; capa[i ^ 1] += g; return g;
        }
      }
      ++itr[u];
    }
    return 0;
  }
  wint augment(int u, wint f) {
    if (ex[u] < 0) {
      wint g = min(f, -ex[u]); ex[u] += g; return g;
    }
    foreach (i; g[u][itr[u] .. $]) {
      if (capa[i] > 0 && cost[i] + pot[u] - pot[zu[i]] < 0) {
        wint g = augment(zu[i], min(f, capa[i]));
        if (g > 0) {
          capa[i] -= g; capa[i ^ 1] += g; return g;
        }
      }
      ++itr[u];
    }
    return 0;
  }
  wint dinic(int s, int t, wint f) {
    wint tof = 0;
    for (; tof < f; ) {
      int[] q;
      lev[] = -1;
      for (lev[s] = 0, q ~= s; !q.empty; ) {
        int u = q.front; q.popFront;
        foreach (i; g[u]) {
          int v = zu[i];
          if (capa[i] > 0 && lev[v] == -1) {
            lev[v] = lev[u] + 1; q ~= v;
          }
        }
      }
      if (lev[t] == -1) break;
      itr[] = 0;
      for (wint g; (g = augment(s, t, f - tof)) > 0; ) tof += g;
    }
    return tof;
  }
  void dfs(int u) {
    if (vis[u]) return; vis[u] = true;
    foreach (i; g[u]) if (capa[i] > 0 && cost[i] + pot[u] - pot[zu[i]] < 0) {
      dfs(zu[i]);
    }
  }
  // cint solve() {
    // real eps = 0;
  cint solve(int s, int t, wint flow) {
    real eps = 1;
    ex[s] += flow;
    ex[t] -= flow;
    foreach (i; 0 .. m) if (capa[i] > 0) chmax(eps, cast(real)(-cost[i]));
    for (; eps * n >= 1; ) {
      eps /= 4;
      foreach (i; 0 .. m) if (capa[i] > 0 && cost[i] + pot[zu[i ^ 1]] - pot[zu[i]] < 0) {
        ex[zu[i ^ 1]] -= capa[i]; ex[zu[i]] += capa[i]; capa[i ^ 1] += capa[i]; capa[i] = 0;
      }
      for (; ; ) {
        vis[] = false; itr[] = 0;
        foreach (u; 0 .. n) if (ex[u] > 0) dfs(u);
        foreach (u; 0 .. n) if (vis[u]) pot[u] -= eps;
        foreach (u; 0 .. n) for (wint f; ex[u] > 0 && (f = augment(u, ex[u])) > 0; ) ex[u] -= f;
        if (ex.all!"a <= 0") break;
      }
    }
    cint toc = 0;
    foreach (i; 0 .. m) if (capa0[i] > capa[i]) toc += (capa0[i] - capa[i]) * cost[i];
    return toc;
  }
}

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      const M = readInt();
      auto U = new int[M];
      auto V = new int[M];
      foreach (i; 0 .. M) {
        U[i] = readInt() - 1;
        V[i] = readInt() - 1;
      }

      auto adj = new int[][](N, N);
      foreach (u; 0 .. N) {
        adj[u][] = -1;
      }
      foreach (i; 0 .. M) {
        adj[U[i]][V[i]] = 1;
        adj[V[i]][U[i]] = 0;
      }
      debug {
        writeln("adj = ", adj);
      }

      auto mcf = new MinCostFlow!(int, int)(2 + N + N * (N - 1) / 2);
      auto ids = new int[][](N, N);
      foreach (u; 0 .. N) {
        // -d (N - 1 - d)
        foreach (d; 0 .. N - 1) {
          const diff = (-(d + 1) * (N - 1 - (d + 1))) - (-d * (N - 1 - d));
          mcf.addEdge(0, 2 + u, 1, diff);
          debug {
            // writeln(u, " ", d, ": ", diff);
          }
        }
      }
      foreach (x; 2 + N .. 2 + N + N * (N - 1) / 2) {
        mcf.addEdge(x, 1, 1, 0);
      }
      foreach (u; 0 .. N) {
        ids[u][] = -1;
      }
      {
        int x = 2 + N;
        foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
          if (adj[u][v] != 0) ids[u][v] = mcf.addEdge(2 + u, x, 1, 0);
          if (adj[v][u] != 0) ids[v][u] = mcf.addEdge(2 + v, x, 1, 0);
          ++x;
        }
        assert(x == 2 + N + N * (N - 1) / 2);
      }
      /*
      const res = mcf.solve(0, 1, N * (N - 1) / 2);
      debug {
        writeln("tof = ", mcf.tof, ", toc = ", mcf.toc);
      }
      assert(res);
      */
      const res = mcf.solve(0, 1, N * (N - 1) / 2);
      debug {
        writeln("res = ", res);
      }

      auto ans = new int[][](N, N);
      foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
        if (ids[u][v] != -1 && mcf.capa[ids[u][v]] == 0) ans[u][v] = 1;
        if (ids[v][u] != -1 && mcf.capa[ids[v][u]] == 0) ans[v][u] = 1;
        // assert(ans[u][v] + ans[v][u] == 1);
      }
      foreach (u; 0 .. N) {
        foreach (v; 0 .. N) {
          write(ans[u][v]);
        }
        writeln();
      }
    }
  } catch (EOFException e) {
  }
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

class MinCostFlow(Capa, Cost, Capa CAPA_EPS = 0) {
  int n, m;
  int[][] g;
  int[] as, bs;
  Capa[] capa;
  Cost[] cost, pot;
  Capa tof;
  Cost toc;
  this(int n) {
    this.n = n; m = 0; g = new int[][n]; as = []; bs = []; capa = []; cost = [];
  }
  int addEdge(int u, int v, Capa w, Cost c) {
    debug {
      writeln("addEdge ", u, " ", v, " ", w, " ", c);
    }
    const i = m;
    g[u] ~= m; as ~= u; bs ~= v; capa ~= w; cost ~= c; ++m;
    g[v] ~= m; as ~= v; bs ~= u; capa ~= 0; cost ~= -c; ++m;
    return i;
  }
  bool solve(int source, int sink, Capa flow) {
    pot = new Cost[n];
    pot[] = 0;
    for (; ; ) {
      bool cont;
      foreach (u; 0 .. n) foreach (i; g[u]) if (capa[i] > CAPA_EPS) {
        const v = bs[i];
        if (pot[v] > pot[u] + cost[i]) {
          pot[v] = pot[u] + cost[i];
          cont = true;
        }
      }
      if (!cont) break;
    }
    auto dist = new Cost[n];
    auto prei = new int[n];
    auto vis = new bool[n];
    for (tof = 0, toc = 0; tof + CAPA_EPS < flow; ) {
      alias Entry = Tuple!(Cost, "c", int, "u");
      BinaryHeap!(Array!Entry, "a > b") que;
      dist[] = -1;
      prei[] = -1;
      vis[] = false;
      dist[source] = 0;
      prei[source] = -2;
      que.insert(Entry(0, source));
      for (; !que.empty(); ) {
        const c = que.front.c;
        const u = que.front.u;
        que.removeFront;
        if (vis[u]) continue;
        vis[u] = true;
        if (u == sink) break;
        foreach (i; g[u]) if (capa[i] > CAPA_EPS) {
          const v = bs[i];
          if (vis[v]) continue;
          const cc = c + cost[i] + pot[u] - pot[v];
          if (prei[v] == -1 || dist[v] > cc) {
            dist[v] = cc;
            prei[v] = i;
            que.insert(Entry(cc, v));
          }
        }
      }
      if (!vis[sink]) return false;
      Capa f = flow - tof;
      for (int v = sink; v != source; ) {
        const i = prei[v];
        if (f > capa[i]) f = capa[i];
        v = as[i];
      }
      for (int v = sink; v != source; ) {
        const i = prei[v];
        capa[i] -= f; capa[i ^ 1] += f;
        v = as[i];
      }
      tof += f;
      toc += f * (dist[sink] - pot[source] + pot[sink]);
      pot[] += dist[];
    }
    return true;
  }
}

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      const M = readInt();
      auto U = new int[M];
      auto V = new int[M];
      foreach (i; 0 .. M) {
        U[i] = readInt() - 1;
        V[i] = readInt() - 1;
      }

      auto adj = new int[][](N, N);
      foreach (u; 0 .. N) {
        adj[u][] = -1;
      }
      foreach (i; 0 .. M) {
        adj[U[i]][V[i]] = 1;
        adj[V[i]][U[i]] = 0;
      }
      debug {
        writeln("adj = ", adj);
      }

      auto mcf = new MinCostFlow!(int, long)(2 + N + N * (N - 1) / 2);
      auto ids = new int[][](N, N);
      foreach (u; 0 .. N) {
        // -d (N - 1 - d)
        foreach (d; 0 .. N - 1) {
          const diff = (-(d + 1) * (N - 1 - (d + 1))) - (-d * (N - 1 - d));
          mcf.addEdge(0, 2 + u, 1, diff);
          debug {
            writeln(u, " ", d, ": ", diff);
          }
        }
      }
      foreach (x; 2 + N .. 2 + N + N * (N - 1) / 2) {
        mcf.addEdge(x, 1, 1, 0);
      }
      foreach (u; 0 .. N) {
        ids[u][] = -1;
      }
      {
        int x = 2 + N;
        foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
          if (adj[u][v] != 0) ids[u][v] = mcf.addEdge(2 + u, x, 1, 0);
          if (adj[v][u] != 0) ids[v][u] = mcf.addEdge(2 + v, x, 1, 0);
          ++x;
        }
        assert(x == 2 + N + N * (N - 1) / 2);
      }
      const res = mcf.solve(0, 1, N * (N - 1) / 2);
      debug {
        writeln("tof = ", mcf.tof, ", toc = ", mcf.toc);
      }
      assert(res);

      auto ans = new int[][](N, N);
      foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
        if (ids[u][v] != -1 && mcf.capa[ids[u][v]] == 0) ans[u][v] = 1;
        if (ids[v][u] != -1 && mcf.capa[ids[v][u]] == 0) ans[v][u] = 1;
        assert(ans[u][v] + ans[v][u] == 1);
      }
      foreach (u; 0 .. N) {
        foreach (v; 0 .. N) {
          write(ans[u][v]);
        }
        writeln();
      }
    }
  } catch (EOFException e) {
  }
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

class MinCostFlow(Capa, Cost, Capa CAPA_EPS = 0) {
  int n, m;
  int[][] g;
  int[] as, bs;
  Capa[] capa;
  Cost[] cost, pot;
  Capa tof;
  Cost toc;
  this(int n) {
    this.n = n; m = 0; g = new int[][n]; as = []; bs = []; capa = []; cost = [];
  }
  int addEdge(int u, int v, Capa w, Cost c) {
    debug {
      writeln("addEdge ", u, " ", v, " ", w, " ", c);
    }
    const i = m;
    g[u] ~= m; as ~= u; bs ~= v; capa ~= w; cost ~= c; ++m;
    g[v] ~= m; as ~= v; bs ~= u; capa ~= 0; cost ~= -c; ++m;
    return i;
  }
  bool solve(int source, int sink, Capa flow) {
    pot = new Cost[n];
    pot[] = 0;
    for (; ; ) {
      bool cont;
      foreach (u; 0 .. n) foreach (i; g[u]) if (capa[i] > CAPA_EPS) {
        const v = bs[i];
        if (pot[v] > pot[u] + cost[i]) {
          pot[v] = pot[u] + cost[i];
          cont = true;
        }
      }
      if (!cont) break;
    }
    for (tof = 0, toc = 0; tof + CAPA_EPS < flow; ) {
      class Heap {
        Heap l, r, p;
        Cost dist;
        int prei, id;
      }
      Heap merge(Heap a, Heap b) {
        if (!a) return b;
        if (!b) return a;
        if (a.dist > b.dist) swap(a, b);
        a.r = merge(a.r, b);
        swap(a.l, a.r);
        if (a.l) a.l.p = a;
        if (a.r) a.r.p = a;
        return a;
      }
      void pop(ref Heap a) {
        a = merge(a.l, a.r);
      }
      void sever(ref Heap a, Heap b) {
        if (a == b || b.p.dist <= b.dist) return;
        ((b.p.l == b) ? b.p.l : b.p.r) = null;
        a = merge(a, b);
      }
      auto nodes = new Heap[n];
      foreach (u; 0 .. n) {
        nodes[u] = new Heap();
        nodes[u].dist = -1;
        nodes[u].prei = -1;
        nodes[u].id = u;
      }
      nodes[source].dist = 0;
      nodes[source].prei = -2;
      Heap que = nodes[source];
      for (; que; ) {
        const u = que.id;
        pop(que);
        foreach (i; g[u]) if (capa[i] > CAPA_EPS) {
          const v = bs[i];
          const cc = nodes[u].dist + cost[i] + pot[u] - pot[v];
          if (nodes[v].prei == -1) {
            nodes[v].dist = cc;
            nodes[v].prei = i;
            que = merge(que, nodes[v]);
          } else if (nodes[v].dist > cc) {
            nodes[v].dist = cc;
            nodes[v].prei = i;
            sever(que, nodes[v]);
          }
        }
      }
      if (nodes[sink].prei == -1) return false;
      Capa f = flow - tof;
      for (int v = sink; v != source; ) {
        const i = nodes[v].prei;
        if (f > capa[i]) f = capa[i];
        v = as[i];
      }
      for (int v = sink; v != source; ) {
        const i = nodes[v].prei;
        capa[i] -= f; capa[i ^ 1] += f;
        v = as[i];
      }
      tof += f;
      toc += f * (nodes[sink].dist - pot[source] + pot[sink]);
      foreach (u; 0 .. n) pot[u] += nodes[u].dist;
    }
    return true;
  }
}

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      const M = readInt();
      auto U = new int[M];
      auto V = new int[M];
      foreach (i; 0 .. M) {
        U[i] = readInt() - 1;
        V[i] = readInt() - 1;
      }

      auto adj = new int[][](N, N);
      foreach (u; 0 .. N) {
        adj[u][] = -1;
      }
      foreach (i; 0 .. M) {
        adj[U[i]][V[i]] = 1;
        adj[V[i]][U[i]] = 0;
      }
      debug {
        writeln("adj = ", adj);
      }

      auto mcf = new MinCostFlow!(int, long)(2 + N + N * (N - 1) / 2);
      auto ids = new int[][](N, N);
      foreach (u; 0 .. N) {
        // -d (N - 1 - d)
        foreach (d; 0 .. N - 1) {
          const diff = (-(d + 1) * (N - 1 - (d + 1))) - (-d * (N - 1 - d));
          mcf.addEdge(0, 2 + u, 1, diff);
          debug {
            writeln(u, " ", d, ": ", diff);
          }
        }
      }
      foreach (x; 2 + N .. 2 + N + N * (N - 1) / 2) {
        mcf.addEdge(x, 1, 1, 0);
      }
      foreach (u; 0 .. N) {
        ids[u][] = -1;
      }
      {
        int x = 2 + N;
        foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
          if (adj[u][v] != 0) ids[u][v] = mcf.addEdge(2 + u, x, 1, 0);
          if (adj[v][u] != 0) ids[v][u] = mcf.addEdge(2 + v, x, 1, 0);
          ++x;
        }
        assert(x == 2 + N + N * (N - 1) / 2);
      }
      const res = mcf.solve(0, 1, N * (N - 1) / 2);
      debug {
        writeln("tof = ", mcf.tof, ", toc = ", mcf.toc);
      }
      assert(res);

      auto ans = new int[][](N, N);
      foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
        if (ids[u][v] != -1 && mcf.capa[ids[u][v]] == 0) ans[u][v] = 1;
        if (ids[v][u] != -1 && mcf.capa[ids[v][u]] == 0) ans[v][u] = 1;
        assert(ans[u][v] + ans[v][u] == 1);
      }
      foreach (u; 0 .. N) {
        foreach (v; 0 .. N) {
          write(ans[u][v]);
        }
        writeln();
      }
    }
  } catch (EOFException e) {
  }
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

class MinCostFlow(Capa, Cost, Capa CAPA_EPS = 0) {
  int n, m;
  int[][] g;
  int[] as, bs;
  Capa[] capa;
  Cost[] cost, pot;
  Capa tof;
  Cost toc;
  this(int n) {
    this.n = n; m = 0; g = new int[][n]; as = []; bs = []; capa = []; cost = [];
  }
  int addEdge(int u, int v, Capa w, Cost c) {
    debug {
      writeln("addEdge ", u, " ", v, " ", w, " ", c);
    }
    const i = m;
    g[u] ~= m; as ~= u; bs ~= v; capa ~= w; cost ~= c; ++m;
    g[v] ~= m; as ~= v; bs ~= u; capa ~= 0; cost ~= -c; ++m;
    return i;
  }
  bool solve(int source, int sink, Capa flow) {
    pot = new Cost[n];
    pot[] = 0;
    for (; ; ) {
      bool cont;
      foreach (u; 0 .. n) foreach (i; g[u]) if (capa[i] > CAPA_EPS) {
        const v = bs[i];
        if (pot[v] > pot[u] + cost[i]) {
          pot[v] = pot[u] + cost[i];
          cont = true;
        }
      }
      if (!cont) break;
    }
    DList!int que;
    auto dist = new Cost[n];
    auto prei = new int[n];
    auto on = new bool[n];
    for (tof = 0, toc = 0; tof + CAPA_EPS < flow; ) {
      dist[] = -1;
      prei[] = -1;
      on[] = false;
      dist[source] = 0;
      prei[source] = -2;
      on[source] = true;
      que ~= source;
      for (; !que.empty; ) {
        const u = que.front;
        que.removeFront;
        on[u] = false;
        foreach (i; g[u]) if (capa[i] > CAPA_EPS) {
          const v = bs[i];
          const cc = dist[u] + cost[i] + pot[u] - pot[v];
          if (prei[v] == -1 || dist[v] > cc) {
            dist[v] = cc;
            prei[v] = i;
            if (!on[v]) {
              on[v] = true;
              que ~= v;
            }
          }
        }
      }
      if (prei[sink] == -1) return false;
      Capa f = flow - tof;
      for (int v = sink; v != source; ) {
        const i = prei[v];
        if (f > capa[i]) f = capa[i];
        v = as[i];
      }
      for (int v = sink; v != source; ) {
        const i = prei[v];
        capa[i] -= f; capa[i ^ 1] += f;
        v = as[i];
      }
      tof += f;
      toc += f * (dist[sink] - pot[source] + pot[sink]);
      pot[] += dist[];
    }
    return true;
  }
}

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      const M = readInt();
      auto U = new int[M];
      auto V = new int[M];
      foreach (i; 0 .. M) {
        U[i] = readInt() - 1;
        V[i] = readInt() - 1;
      }

      auto adj = new int[][](N, N);
      foreach (u; 0 .. N) {
        adj[u][] = -1;
      }
      foreach (i; 0 .. M) {
        adj[U[i]][V[i]] = 1;
        adj[V[i]][U[i]] = 0;
      }
      debug {
        writeln("adj = ", adj);
      }

      auto mcf = new MinCostFlow!(int, long)(2 + N + N * (N - 1) / 2);
      auto ids = new int[][](N, N);
      foreach (u; 0 .. N) {
        // -d (N - 1 - d)
        foreach (d; 0 .. N - 1) {
          const diff = (-(d + 1) * (N - 1 - (d + 1))) - (-d * (N - 1 - d));
          mcf.addEdge(0, 2 + u, 1, diff);
          debug {
            writeln(u, " ", d, ": ", diff);
          }
        }
      }
      foreach (x; 2 + N .. 2 + N + N * (N - 1) / 2) {
        mcf.addEdge(x, 1, 1, 0);
      }
      foreach (u; 0 .. N) {
        ids[u][] = -1;
      }
      {
        int x = 2 + N;
        foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
          if (adj[u][v] != 0) ids[u][v] = mcf.addEdge(2 + u, x, 1, 0);
          if (adj[v][u] != 0) ids[v][u] = mcf.addEdge(2 + v, x, 1, 0);
          ++x;
        }
        assert(x == 2 + N + N * (N - 1) / 2);
      }
      const res = mcf.solve(0, 1, N * (N - 1) / 2);
      debug {
        writeln("tof = ", mcf.tof, ", toc = ", mcf.toc);
      }
      assert(res);

      auto ans = new int[][](N, N);
      foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
        if (ids[u][v] != -1 && mcf.capa[ids[u][v]] == 0) ans[u][v] = 1;
        if (ids[v][u] != -1 && mcf.capa[ids[v][u]] == 0) ans[v][u] = 1;
        assert(ans[u][v] + ans[v][u] == 1);
      }
      foreach (u; 0 .. N) {
        foreach (v; 0 .. N) {
          write(ans[u][v]);
        }
        writeln();
      }
    }
  } catch (EOFException e) {
  }
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

class MinCostFlow(Capa, Cost, Capa CAPA_EPS = 0) {
  int n, m;
  int[][] g;
  int[] as, bs;
  Capa[] capa;
  Cost[] cost, pot;
  Capa tof;
  Cost toc;
  this(int n) {
    this.n = n; m = 0; g = new int[][n]; as = []; bs = []; capa = []; cost = [];
  }
  int addEdge(int u, int v, Capa w, Cost c) {
    debug {
      writeln("addEdge ", u, " ", v, " ", w, " ", c);
    }
    const i = m;
    g[u] ~= m; as ~= u; bs ~= v; capa ~= w; cost ~= c; ++m;
    g[v] ~= m; as ~= v; bs ~= u; capa ~= 0; cost ~= -c; ++m;
    return i;
  }
  bool solve(int source, int sink, Capa flow) {
    pot = new Cost[n];
    pot[] = 0;
    for (; ; ) {
      bool cont;
      foreach (u; 0 .. n) foreach (i; g[u]) if (capa[i] > CAPA_EPS) {
        const v = bs[i];
        if (pot[v] > pot[u] + cost[i]) {
          pot[v] = pot[u] + cost[i];
          cont = true;
        }
      }
      if (!cont) break;
    }
    auto dist = new Cost[n];
    auto prei = new int[n];
    auto vis = new bool[n];
    for (tof = 0, toc = 0; tof + CAPA_EPS < flow; ) {
      alias Entry = Tuple!(Cost, "c", int, "u");
      BinaryHeap!(Array!Entry, "a > b") que;
      dist[] = -1;
      prei[] = -1;
      vis[] = false;
      dist[source] = 0;
      prei[source] = -2;
      que.insert(Entry(0, source));
      for (; !que.empty(); ) {
        const c = que.front.c;
        const u = que.front.u;
        que.removeFront;
        if (vis[u]) continue;
        vis[u] = true;
        if (u == sink) break;
        foreach (i; g[u]) if (capa[i] > CAPA_EPS) {
          const v = bs[i];
          if (vis[v]) continue;
          const cc = c + cost[i] + pot[u] - pot[v];
          if (prei[v] == -1 || dist[v] > cc) {
            dist[v] = cc;
            prei[v] = i;
            que.insert(Entry(cc, v));
          }
        }
      }
      if (!vis[sink]) return false;
      Capa f = flow - tof;
      for (int v = sink; v != source; ) {
        const i = prei[v];
        if (f > capa[i]) f = capa[i];
        v = as[i];
      }
      for (int v = sink; v != source; ) {
        const i = prei[v];
        capa[i] -= f; capa[i ^ 1] += f;
        v = as[i];
      }
      tof += f;
      toc += f * (dist[sink] - pot[source] + pot[sink]);
      foreach (u; 0 .. n) if (vis[u]) pot[u] += dist[u];
    }
    return true;
  }
}

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      const M = readInt();
      auto U = new int[M];
      auto V = new int[M];
      foreach (i; 0 .. M) {
        U[i] = readInt() - 1;
        V[i] = readInt() - 1;
      }

      auto adj = new int[][](N, N);
      foreach (u; 0 .. N) {
        adj[u][] = -1;
      }
      foreach (i; 0 .. M) {
        adj[U[i]][V[i]] = 1;
        adj[V[i]][U[i]] = 0;
      }
      debug {
        writeln("adj = ", adj);
      }

      auto mcf = new MinCostFlow!(int, long)(2 + N + N * (N - 1) / 2);
      auto ids = new int[][](N, N);
      foreach (u; 0 .. N) {
        // -d (N - 1 - d)
        foreach (d; 0 .. N - 1) {
          const diff = (-(d + 1) * (N - 1 - (d + 1))) - (-d * (N - 1 - d));
          mcf.addEdge(0, 2 + u, 1, diff);
          debug {
            writeln(u, " ", d, ": ", diff);
          }
        }
      }
      foreach (x; 2 + N .. 2 + N + N * (N - 1) / 2) {
        mcf.addEdge(x, 1, 1, 0);
      }
      foreach (u; 0 .. N) {
        ids[u][] = -1;
      }
      {
        int x = 2 + N;
        foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
          if (adj[u][v] != 0) ids[u][v] = mcf.addEdge(2 + u, x, 1, 0);
          if (adj[v][u] != 0) ids[v][u] = mcf.addEdge(2 + v, x, 1, 0);
          ++x;
        }
        assert(x == 2 + N + N * (N - 1) / 2);
      }
      const res = mcf.solve(0, 1, N * (N - 1) / 2);
      debug {
        writeln("tof = ", mcf.tof, ", toc = ", mcf.toc);
      }
      assert(res);

      auto ans = new int[][](N, N);
      foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
        if (ids[u][v] != -1 && mcf.capa[ids[u][v]] == 0) ans[u][v] = 1;
        if (ids[v][u] != -1 && mcf.capa[ids[v][u]] == 0) ans[v][u] = 1;
        assert(ans[u][v] + ans[v][u] == 1);
      }
      foreach (u; 0 .. N) {
        foreach (v; 0 .. N) {
          write(ans[u][v]);
        }
        writeln();
      }
    }
  } catch (EOFException e) {
  }
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

class MinCostFlow(wint, cint) {
  int n, m;
  int[][] g;
  int[] zu;
  wint[] capa0, capa, ex;
  cint[] cost;
  real[] pot;
  bool[] vis;
  int[] itr, lev;
  this(int n) {
    this.n = n; m = 0; g = new int[][n]; zu = null; capa = null; cost = null;
    ex = new wint[n]; pot = new real[n]; pot[] = 0; vis = new bool[n]; itr = new int[n]; lev = new int[n];
  }
  int addEdge(int u, int v, wint w, cint c) {
    debug {
      writeln("addEdge ", u, " ", v, " ", w, " ", c);
    }
    const i = m;
    g[u] ~= m; zu ~= v; capa0 ~= w; capa ~= w; cost ~= +c; ++m;
    g[v] ~= m; zu ~= u; capa0 ~= 0; capa ~= 0; cost ~= -c; ++m;
    return i;
  }
  wint augment(int u, int t, wint f) {
    if (u == t) return f;
    foreach (i; g[u][itr[u] .. $]) {
      if (capa[i] > 0 && lev[u] < lev[zu[i]]) {
        wint g = augment(zu[i], t, min(f, capa[i]));
        if (g > 0) {
          capa[i] -= g; capa[i ^ 1] += g; return g;
        }
      }
      ++itr[u];
    }
    return 0;
  }
  wint augment(int u, wint f) {
    if (ex[u] < 0) {
      wint g = min(f, -ex[u]); ex[u] += g; return g;
    }
    foreach (i; g[u][itr[u] .. $]) {
      if (capa[i] > 0 && cost[i] + pot[u] - pot[zu[i]] < 0) {
        wint g = augment(zu[i], min(f, capa[i]));
        if (g > 0) {
          capa[i] -= g; capa[i ^ 1] += g; return g;
        }
      }
      ++itr[u];
    }
    return 0;
  }
  wint dinic(int s, int t, wint f) {
    wint tof = 0;
    for (; tof < f; ) {
      int[] q;
      lev[] = -1;
      for (lev[s] = 0, q ~= s; !q.empty; ) {
        int u = q.front; q.popFront;
        foreach (i; g[u]) {
          int v = zu[i];
          if (capa[i] > 0 && lev[v] == -1) {
            lev[v] = lev[u] + 1; q ~= v;
          }
        }
      }
      if (lev[t] == -1) break;
      itr[] = 0;
      for (wint g; (g = augment(s, t, f - tof)) > 0; ) tof += g;
    }
    return tof;
  }
  void dfs(int u) {
    if (vis[u]) return; vis[u] = true;
    foreach (i; g[u]) if (capa[i] > 0 && cost[i] + pot[u] - pot[zu[i]] < 0) {
      dfs(zu[i]);
    }
  }
  cint solve() {
    real eps = 0;
  // cint solve(int s, int t, wint flow) {
    // real eps = 1;
    // ex[s] += flow;
    // ex[t] -= flow;
    foreach (i; 0 .. m) if (capa[i] > 0) chmax(eps, cast(real)(-cost[i]));
    for (; eps * n >= 1; ) {
      eps /= 4;
      foreach (i; 0 .. m) if (capa[i] > 0 && cost[i] + pot[zu[i ^ 1]] - pot[zu[i]] < 0) {
        ex[zu[i ^ 1]] -= capa[i]; ex[zu[i]] += capa[i]; capa[i ^ 1] += capa[i]; capa[i] = 0;
      }
      for (; ; ) {
        vis[] = false; itr[] = 0;
        foreach (u; 0 .. n) if (ex[u] > 0) dfs(u);
        foreach (u; 0 .. n) if (vis[u]) pot[u] -= eps;
        foreach (u; 0 .. n) for (wint f; ex[u] > 0 && (f = augment(u, ex[u])) > 0; ) ex[u] -= f;
        if (ex.all!"a <= 0") break;
      }
    }
    cint toc = 0;
    foreach (i; 0 .. m) if (capa0[i] > capa[i]) toc += (capa0[i] - capa[i]) * cost[i];
    return toc;
  }
}

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      const M = readInt();
      auto U = new int[M];
      auto V = new int[M];
      foreach (i; 0 .. M) {
        U[i] = readInt() - 1;
        V[i] = readInt() - 1;
      }

      auto adj = new int[][](N, N);
      foreach (u; 0 .. N) {
        adj[u][] = -1;
      }
      foreach (i; 0 .. M) {
        adj[U[i]][V[i]] = 1;
        adj[V[i]][U[i]] = 0;
      }
      debug {
        writeln("adj = ", adj);
      }

      auto mcf = new MinCostFlow!(int, int)(2 + N + N * (N - 1) / 2);
      auto ids = new int[][](N, N);
      foreach (u; 0 .. N) {
        // -d (N - 1 - d)
        foreach (d; 0 .. N - 1) {
          const diff = (-(d + 1) * (N - 1 - (d + 1))) - (-d * (N - 1 - d));
          mcf.addEdge(0, 2 + u, 1, diff);
          debug {
            // writeln(u, " ", d, ": ", diff);
          }
        }
      }
      foreach (x; 2 + N .. 2 + N + N * (N - 1) / 2) {
        mcf.addEdge(x, 1, 1, 0);
      }
      foreach (u; 0 .. N) {
        ids[u][] = -1;
      }
      {
        int x = 2 + N;
        foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
          if (adj[u][v] != 0) ids[u][v] = mcf.addEdge(2 + u, x, 1, 0);
          if (adj[v][u] != 0) ids[v][u] = mcf.addEdge(2 + v, x, 1, 0);
          ++x;
        }
        assert(x == 2 + N + N * (N - 1) / 2);
      }
      /*
      const res = mcf.solve(0, 1, N * (N - 1) / 2);
      debug {
        writeln("tof = ", mcf.tof, ", toc = ", mcf.toc);
      }
      assert(res);
      */
      mcf.addEdge(1, 0, N * (N - 1) / 2, -2 * N);
      const res = mcf.solve;
      // const res = mcf.solve(0, 1, N * (N - 1) / 2);
      debug {
        writeln("res = ", res);
      }

      auto ans = new int[][](N, N);
      foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
        if (ids[u][v] != -1 && mcf.capa[ids[u][v]] == 0) ans[u][v] = 1;
        if (ids[v][u] != -1 && mcf.capa[ids[v][u]] == 0) ans[v][u] = 1;
        // assert(ans[u][v] + ans[v][u] == 1);
      }
      foreach (u; 0 .. N) {
        foreach (v; 0 .. N) {
          write(ans[u][v]);
        }
        writeln();
      }
    }
  } catch (EOFException e) {
  }
}

/+ dub.sdl:
    name "X"
    dependency "dunkelheit" version="1.0.1"
+/

import std.stdio, std.algorithm, std.range, std.conv;
// import dkh.foundation, dkh.scanner, dkh.graph.mincostflow;

int main() {
    Scanner sc = new Scanner(stdin);
    scope(exit) assert(!sc.hasNext);

    int n, m;
    sc.read(n, m);
    int ec = n * (n - 1) / 2;
    int v = ec + n + 2;
    int sv = ec + n, tv = sv + 1;
    struct E {
        int to, rev, cap, dist;
    }
    E[][] g = new E[][](v);
    void addEdge(int from, int to, int cap, int dist) {
        g[from] ~= E(to, g[to].length.to!int, cap, dist);
        g[to] ~= E(from, g[from].length.to!int-1, 0, -dist);
    }
    int[][] def = new int[][](n, n);
    foreach (i; 0..m) {
        int a, b;
        sc.read(a, b); a--; b--;
        def[a][b] = 1;
        def[b][a] = -1;
    }
    int id = 0;
    foreach (i; 0..n) {
        foreach (j; i + 1..n) {
            addEdge(sv, id, 1, 0);
            if (def[i][j] != -1) {
                addEdge(id, ec + i, 1, 0);
            }
            if (def[j][i] != -1) {
                addEdge(id, ec + j, 1, 0);
            }
            id++;
        }
    }
    foreach (i; 0..n) {
        foreach (j; 1..n+1) {
            addEdge(ec + i, tv, 1, j - 1);
        }
    }
    auto mcfInfo = minCostFlow!(int, int, 0)(g, sv, tv, false);
    mcfInfo.manyFlow(10^^9);

    int[][] ans = new int[][](n, n);
    id = 0;
    foreach (i; 0..n) {
        foreach (j; i + 1..n) {
            foreach (e; g[id]) {
                if (e.to < ec || ec + n <= e.to) continue;
                if (e.cap) continue;
                if (e.to == ec + i) ans[i][j] = 1;
                else ans[j][i] = 1;
                break;
            }
            id++;
        }
    }

    foreach (i; 0..n) {
        foreach (j; 0..n) {
            write(ans[i][j], " ");
        }
        writeln;
    }
    return 0;
}
/* IMPORT /Users/yosupo/Programs/dunkelheit/source/dkh/foundation.d */

// module dkh.foundation;

static if (__VERSION__ <= 2070) {
    /*
    Copied by https://github.com/dlang/phobos/blob/master/std/algorithm/iteration.d
    Copyright: Andrei Alexandrescu 2008-.
    License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
    */
    template fold(fun...) if (fun.length >= 1) {
        auto fold(R, S...)(R r, S seed) {
            import std.algorithm : reduce;
            static if (S.length < 2) {
                return reduce!fun(seed, r);
            } else {
                import std.typecons : tuple;
                return reduce!fun(tuple(seed), r);
            }
        }
    }

}
/* IMPORT /Users/yosupo/Programs/dunkelheit/source/dkh/container/deque.d */
// module dkh.container.deque;

struct DequePayload(T) {
    import core.exception : RangeError;

    private T* _data;
    private uint start, len, cap;

    @property bool empty() const { return len == 0; }
    @property size_t length() const { return len; }
    alias opDollar = length;

    ref inout(T) opIndex(size_t i) inout {
        version(assert) if (len <= i) throw new RangeError();
        if (start + i < cap) return _data[start + i];
        else return _data[start + i - cap];
    }
    ref inout(T) front() inout { return this[0]; }
    ref inout(T) back() inout { return this[$-1]; }

    void reserve(size_t newCap) {
        import core.memory : GC;
        import std.algorithm : max;
        import std.conv : to;
        if (newCap <= cap) return;
        T* newData = cast(T*)GC.malloc(newCap * T.sizeof);
        foreach (i; 0..length) {
            newData[i] = this[i];
        }
        _data = newData; start = 0; cap = newCap.to!uint;
    }
    void clear() {
        start = len = 0;
    }
    import std.algorithm : max;
    void insertFront(T item) {
        if (len == cap) reserve(max(cap * 2, 4));
        if (start == 0) start += cap;
        start--; len++;
        this[0] = item;
    }
    void insertBack(T item) {
        if (len == cap) reserve(max(cap * 2, 4));
        len++;
        this[len-1] = item;
    }
    void removeFront() {
        assert(!empty, "Deque.removeFront: Deque is empty");
        start++; len--;
        if (start == cap) start = 0;
    }
    void removeBack() {
        assert(!empty, "Deque.removeBack: Deque is empty");
        len--;
    }
}

struct Deque(T, bool mayNull = true) {
    import core.exception : RangeError;
    import std.range : ElementType, isInputRange;
    import std.traits : isImplicitlyConvertible;

    alias Payload = DequePayload!T;
    Payload* _p;

    static if (!mayNull) @disable this();

    this(U)(U[] values...) if (isImplicitlyConvertible!(U, T)) {
        _p = new Payload();
        foreach (v; values) {
            insertBack(v);
        }
    }

    this(Range)(Range r)
    if (isInputRange!Range &&
    isImplicitlyConvertible!(ElementType!Range, T) &&
    !is(Range == T[])) {
        _p = new Payload();
        foreach (v; r) {
            insertBack(v);
        }
    }
    private this(Payload* p) { _p = p; }
    static Deque make() { return Deque(new Payload()); }

    private bool havePayload() const { return (!mayNull || _p); }
    @property bool empty() const { return (!havePayload || _p.empty); }
    @property size_t length() const { return (havePayload ? _p.length : 0); }
    alias opDollar = length;

    ref inout(T) opIndex(size_t i) inout {
        assert(!empty, "Deque.opIndex: Deque is empty");
        return (*_p)[i];
    }
    ref inout(T) front() inout { return this[0]; }
    ref inout(T) back() inout { return this[$-1]; }

    void clear() { if (_p) _p.clear(); }

    void insertFront(T item) {
        if (mayNull && !_p) _p = new Payload();
        _p.insertFront(item);
    }
    void insertBack(T item) {
        if (mayNull && !_p) _p = new Payload();
        _p.insertBack(item);
    }
    alias opOpAssign(string op : "~") = insertBack;
    alias stableInsertBack = insertBack;

    void removeFront() {
        assert(!mayNull || _p, "Deque.removeFront: Deque is empty");
        _p.removeFront();
    }
    void removeBack() {
        assert(!mayNull || _p, "Deque.removeBack: Deque is empty");
        _p.removeBack();
    }
    alias stableRemoveBack = removeBack;

    alias Range = RangeT!(DequePayload!T);
    alias ConstRange = RangeT!(const DequePayload!T);
    alias ImmutableRange = RangeT!(immutable DequePayload!T);

    size_t[2] opSlice(size_t dim : 0)(size_t start, size_t end) const {
        assert(start <= end && end <= length);
        return [start, end];
    }
    Range opIndex(size_t[2] rng) { return Range(_p, rng[0], rng[1]); }
    ConstRange opIndex(size_t[2] rng) const { return ConstRange(_p, rng[0], rng[1]); }
    ImmutableRange opIndex(size_t[2] rng) immutable { return ImmutableRange(_p, rng[0], rng[1]); }
    auto opIndex() inout { return this[0..$]; }

    static struct RangeT(QualifiedPayload) {
        alias A = QualifiedPayload;
        import std.traits : CopyTypeQualifiers;
        alias E = CopyTypeQualifiers!(A, T);
        A *p;
        size_t l, r;

        @property bool empty() const { return r <= l; }
        @property size_t length() const { return r - l; }
        alias opDollar = length;

        @property auto save() { return this; }

        ref inout(E) opIndex(size_t i) inout {
            version(assert) if (empty) throw new RangeError();
            return (*p)[l+i];
        }
        @property ref inout(E) front() inout { return this[0]; }
        @property ref inout(E) back() inout { return this[$-1]; }

        void popFront() {
            version(assert) if (empty) throw new RangeError();
            l++;
        }
        void popBack() {
            version(assert) if (empty) throw new RangeError();
            r--;
        }

        size_t[2] opSlice(size_t dim : 0)(size_t start, size_t end) const {
            assert(start <= end && end <= length);
            return [start, end];
        }
        auto opIndex(size_t[2] rng) { return RangeT(p, l+rng[0], l+rng[1]); }
        auto opIndex(size_t[2] rng) const { return RangeT!(const A)(p, l+rng[0], l+rng[1]); }
        auto opIndex(size_t[2] rng) immutable { return RangeT!(immutable A)(p, l+rng[0], l+rng[1]); }
        auto opIndex() inout { return this[0..$]; }
    }
}

/* IMPORT /Users/yosupo/Programs/dunkelheit/source/dkh/container/radixheap.d */
// module dkh.container.radixheap;

// import dkh.container.stackpayload;

import std.functional : unaryFun;
import std.traits : isSigned, isUnsigned;

template RadixHeap(T, alias pred = "a") {
    alias _pred = unaryFun!pred;
    alias K = typeof(_pred(T()));

    static if (isUnsigned!K) {

        struct RadixHeap {
            static struct Payload {
                StackPayload!T[K.sizeof*8+1] v;
                size_t len;
                K last;

                private static int bsr1(K x) {
                    import core.bitop : bsr;
                    return (x == 0) ? 0 : bsr(x)+1;
                }
                private void assign(T item) {
                    K key = _pred(item);
                    assert(last <= key);
                    v[bsr1(key^last)] ~= item;
                }
                private void pull() {
                    import std.range, std.algorithm;
                    if (v[0].length) return;
                    auto i = iota(K.sizeof*8+1).find!(a => v[a].length).front;

                    last = v[i].data[].map!_pred.reduce!min;
                    v[i].data.each!(a => assign(a));
                    v[i].clear();
                }

                void insert(T item) {
                    len++;
                    assign(item);
                }
                T front() {
                    pull();
                    return v[0].back;
                }
                void removeFront() {
                    pull();
                    len--;
                    v[0].removeBack();
                }
            }
            Payload* p;

            @property bool empty() const { return (!p || p.len == 0); }
            @property size_t length() const { return (!p ? 0 : p.len); }
            alias opDollar = length;

            T front() {
                assert(!empty, "RadixHeap.front: heap is empty");
                return p.front;
            }
            void insert(T item) {
                if (!p) p = new Payload();
                p.insert(item);
            }
            void removeFront() {
                assert(!empty, "RadixHeap.removeFront: heap is empty");
                p.removeFront();
            }
        }
    } else static if (isSigned!K) {

        import std.traits : Unsigned;
        static Unsigned!K pred2(in T item) {
            return _pred(item) ^ (K(1) << (K.sizeof*8 - 1));
        }
        alias RadixHeap = RadixHeap!(T, pred2);
    } else {
        static assert(false);
    }
}

/* IMPORT /Users/yosupo/Programs/dunkelheit/source/dkh/graph/mincostflow.d */
// module dkh.graph.mincostflow;

// import dkh.container.deque;

struct MinCostFlowInfo(C, D, D EPS, T) {
    T g;
    int s, t;
    C nc, capFlow;
    D nd, flow;
    D[] dual;
    private int[] pv, pe;
    this(T g, int s, int t) {
        this.g = g;
        this.s = s;
        this.t = t;
        flow = D(0);
        dual = new D[g.length]; dual[] = D(0);
        pv = new int[g.length];
        pe = new int[g.length];
    }
}

MinCostFlowInfo!(C, D, EPS, T) minCostFlow(C, D, D EPS, T)(T g, int s, int t, bool neg = false) {
    assert(s != t);
    auto mcfInfo = MinCostFlowInfo!(C, D, EPS, T)(g, s, t);
    mcfInfo.dualRef(neg);
    return mcfInfo;
}

C singleFlow(C, D, alias EPS, T)(ref MinCostFlowInfo!(C, D, EPS, T) mcfInfo, C c) {
    import std.algorithm;
    with (mcfInfo) {
        if (nd == D.max) return nc;
        c = min(c, nc);
        for (int v = t; v != s; v = pv[v]) {
            g[pv[v]][pe[v]].cap -= c;
            g[v][g[pv[v]][pe[v]].rev].cap += c;
        }
        capFlow += c;
        flow += c * nd;
        nc -= c;
        if (!nc) dualRef(mcfInfo, false);
    }
    return c;
}

void manyFlow(C, D, alias EPS, T)(ref MinCostFlowInfo!(C, D, EPS, T) mcfInfo, C c) {
    with (mcfInfo) {
        while (c) {
            C f = singleFlow(mcfInfo, c);
            if (!f) break;
            c -= f;
        }
    }
}

// import dkh.container.stackpayload;
// import dkh.container.radixheap;

void dualRef(bool neg, C, D, alias EPS, T)(ref MinCostFlowInfo!(C, D, EPS, T) mcfInfo) {
    import std.conv : to;
    import std.traits : isIntegral;
    import std.typecons;
    import std.container;
    import std.algorithm;
    alias P = Tuple!(int, "to", D, "dist");

    with(mcfInfo) {
        int n = g.length.to!int;
        D[] dist = new D[n]; dist[] = D.max;
        pv[] = -1; pe[] = -1;
        StackPayload!int refV;
        auto que = (){
            static if (!neg) {
                static if (isIntegral!D) {
                    return RadixHeap!(P, "a.dist")();
                } else {
                    return heapify!"a.dist>b.dist"(make!(Array!P));
                }
            } else {
                return Deque!P();
            }
        }();
        void insert(P p) {
            static if (!neg) {
                que.insert(p);
            } else {
                que.insertBack(p);
            }
        }
        P pop() {
            P p;
            static if (!neg) {
                p = que.front();
                que.removeFront();
            } else {
                p = que.back();
                que.removeBack();
            }
            return p;
        }
        insert(P(s, D(0)));
        dist[s] = D(0);
        while (!que.empty) {
            P p = pop();
            int v = p.to;
            if (dist[v] < p.dist) continue;
            if (!neg) {
                if (v == t) break;
                refV ~= v;
            }
            foreach (int i, e; g[v]) {
                D ed = e.dist + dual[v] - dual[e.to];
                if (e.cap && dist[e.to] > dist[v] + ed + EPS) {
                    dist[e.to] = dist[v] + ed;
                    pv[e.to] = v; pe[e.to] = i;
                    insert(P(e.to, dist[e.to]));
                }
            }
        }
        if (dist[t] == D.max) {
            nd = D.max;
            nc = 0;
            return;
        }
        static if (!neg) {
            foreach (v; refV.data) {
                if (dist[v] >= dist[t]) continue;
                dual[v] += dist[v]-dist[t];
            }
        } else {
            for (int v = 0; v < n; v++) {
                if (dist[v] == D.max) dual[v] = D.max;
                else dual[v] += dist[v];
            }
        }

        nd = dual[t]-dual[s];
        nc = C.max;
        for (int v = t; v != s; v = pv[v]) {
            nc = min(nc, g[pv[v]][pe[v]].cap);
        }
    }
}

void dualRef(C, D, alias EPS, T)(ref MinCostFlowInfo!(C, D, EPS, T) mcfInfo, bool neg) {
    if (neg == false) {
        dualRef!false(mcfInfo);
    } else {
        dualRef!true(mcfInfo);
    }
}

/* IMPORT /Users/yosupo/Programs/dunkelheit/source/dkh/container/stackpayload.d */
// module dkh.container.stackpayload;

struct StackPayload(T, size_t MINCAP = 4) if (MINCAP >= 1) {
    import core.exception : RangeError;

    private T* _data;
    private uint len, cap;

    @property bool empty() const { return len == 0; }
    @property size_t length() const { return len; }
    alias opDollar = length;

    inout(T)[] data() inout { return (_data) ? _data[0..len] : null; }

    ref inout(T) opIndex(size_t i) inout {
        version(assert) if (len <= i) throw new RangeError();
        return _data[i];
    }
    ref inout(T) front() inout { return this[0]; }
    ref inout(T) back() inout { return this[$-1]; }

    void reserve(size_t newCap) {
        import core.memory : GC;
        import core.stdc.string : memcpy;
        import std.conv : to;
        if (newCap <= cap) return;
        void* newData = GC.malloc(newCap * T.sizeof);
        cap = newCap.to!uint;
        if (len) memcpy(newData, _data, len * T.sizeof);
        _data = cast(T*)(newData);
    }
    void free() {
        import core.memory : GC;
        GC.free(_data);
    }

    void clear() {
        len = 0;
    }

    void insertBack(T item) {
        import std.algorithm : max;
        if (len == cap) reserve(max(cap * 2, MINCAP));
        _data[len++] = item;
    }
    alias opOpAssign(string op : "~") = insertBack;
    void removeBack() {
        assert(!empty, "StackPayload.removeBack: Stack is empty");
        len--;
    }
}

/* IMPORT /Users/yosupo/Programs/dunkelheit/source/dkh/scanner.d */
// module dkh.scanner;

// import dkh.container.stackpayload;

class Scanner {
    import std.stdio : File;
    import std.conv : to;
    import std.range : front, popFront, array, ElementType;
    import std.array : split;
    import std.traits : isSomeChar, isStaticArray, isArray;
    import std.algorithm : map;
    private File f;

    this(File f) {
        this.f = f;
    }
    private char[512] lineBuf;
    private char[] line;
    private bool succW() {
        import std.range.primitives : empty, front, popFront;
        import std.ascii : isWhite;
        while (!line.empty && line.front.isWhite) {
            line.popFront;
        }
        return !line.empty;
    }
    private bool succ() {
        import std.range.primitives : empty, front, popFront;
        import std.ascii : isWhite;
        while (true) {
            while (!line.empty && line.front.isWhite) {
                line.popFront;
            }
            if (!line.empty) break;
            line = lineBuf[];
            f.readln(line);
            if (!line.length) return false;
        }
        return true;
    }

    private bool readSingle(T)(ref T x) {
        import std.algorithm : findSplitBefore;
        import std.string : strip;
        import std.conv : parse;
        if (!succ()) return false;
        static if (isArray!T) {
            alias E = ElementType!T;
            static if (isSomeChar!E) {

                auto r = line.findSplitBefore(" ");
                x = r[0].strip.dup;
                line = r[1];
            } else static if (isStaticArray!T) {
                foreach (i; 0..T.length) {
                    assert(succW());
                    x[i] = line.parse!E;
                }
            } else {
                StackPayload!E buf;
                while (succW()) {
                    buf ~= line.parse!E;
                }
                x = buf.data;
            }
        } else {
            x = line.parse!T;
        }
        return true;
    }

    int unsafeRead(T, Args...)(ref T x, auto ref Args args) {
        if (!readSingle(x)) return 0;
        static if (args.length == 0) {
            return 1;
        } else {
            return 1 + read(args);
        }
    }

    void read(Args...)(auto ref Args args) {
        import std.exception : enforce;
        static if (args.length != 0) {
            enforce(readSingle(args[0]));
            read(args[1..$]);
        }
    }

    bool hasNext() {
        return succ();
    }
}

/*
This source code generated by dunkelheit and include dunkelheit's source code.
dunkelheit's Copyright: Copyright (c) 2016- Kohei Morita. (https://github.com/yosupo06/dunkelheit)
dunkelheit's License: MIT License(https://github.com/yosupo06/dunkelheit/blob/master/LICENSE.txt)
*/

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

class MinCostFlow(Capa, Cost, Capa CAPA_EPS = 0) {
  int n, m;
  int[][] g;
  int[] as, bs;
  Capa[] capa;
  Cost[] cost, pot;
  Capa tof;
  Cost toc;
  this(int n) {
    this.n = n; m = 0; g = new int[][n]; as = []; bs = []; capa = []; cost = [];
  }
  int addEdge(int u, int v, Capa w, Cost c) {
    debug {
      writeln("addEdge ", u, " ", v, " ", w, " ", c);
    }
    const i = m;
    g[u] ~= m; as ~= u; bs ~= v; capa ~= w; cost ~= c; ++m;
    g[v] ~= m; as ~= v; bs ~= u; capa ~= 0; cost ~= -c; ++m;
    return i;
  }
  bool solve(int source, int sink, Capa flow) {
    pot = new Cost[n];
    pot[] = 0;
    for (; ; ) {
      bool cont;
      foreach (u; 0 .. n) foreach (i; g[u]) if (capa[i] > CAPA_EPS) {
        const v = bs[i];
        if (pot[v] > pot[u] + cost[i]) {
          pot[v] = pot[u] + cost[i];
          cont = true;
        }
      }
      if (!cont) break;
    }
    auto dist = new Cost[n];
    auto prei = new int[n];
    auto on = new bool[n];
    for (tof = 0, toc = 0; tof + CAPA_EPS < flow; ) {
      DList!int que;
      dist[] = -1;
      prei[] = -1;
      on[] = false;
      dist[source] = 0;
      prei[source] = -2;
      on[source] = true;
      que ~= source;
      for (; !que.empty(); ) {
        const u = que.front;
        que.removeFront;
        on[u] = false;
        if (u == sink) break;
        foreach (i; g[u]) if (capa[i] > CAPA_EPS) {
          const v = bs[i];
          const cc = dist[u] + cost[i] + pot[u] - pot[v];
          if (prei[v] == -1 || dist[v] > cc) {
            dist[v] = cc;
            prei[v] = i;
            if (!on[v]) {
              on[v] = true;
              que ~= v;
            }
          }
        }
      }
      if (prei[sink] == -1) return false;
      Capa f = flow - tof;
      for (int v = sink; v != source; ) {
        const i = prei[v];
        if (f > capa[i]) f = capa[i];
        v = as[i];
      }
      for (int v = sink; v != source; ) {
        const i = prei[v];
        capa[i] -= f; capa[i ^ 1] += f;
        v = as[i];
      }
      tof += f;
      toc += f * (dist[sink] - pot[source] + pot[sink]);
      pot[] += dist[];
    }
    return true;
  }
}

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      const M = readInt();
      auto U = new int[M];
      auto V = new int[M];
      foreach (i; 0 .. M) {
        U[i] = readInt() - 1;
        V[i] = readInt() - 1;
      }

      auto adj = new int[][](N, N);
      foreach (u; 0 .. N) {
        adj[u][] = -1;
      }
      foreach (i; 0 .. M) {
        adj[U[i]][V[i]] = 1;
        adj[V[i]][U[i]] = 0;
      }
      debug {
        writeln("adj = ", adj);
      }

      auto mcf = new MinCostFlow!(int, long)(2 + N + N * (N - 1) / 2);
      auto ids = new int[][](N, N);
      foreach (u; 0 .. N) {
        // -d (N - 1 - d)
        foreach (d; 0 .. N - 1) {
          const diff = (-(d + 1) * (N - 1 - (d + 1))) - (-d * (N - 1 - d));
          mcf.addEdge(0, 2 + u, 1, diff);
          debug {
            writeln(u, " ", d, ": ", diff);
          }
        }
      }
      foreach (x; 2 + N .. 2 + N + N * (N - 1) / 2) {
        mcf.addEdge(x, 1, 1, 0);
      }
      foreach (u; 0 .. N) {
        ids[u][] = -1;
      }
      {
        int x = 2 + N;
        foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
          if (adj[u][v] != 0) ids[u][v] = mcf.addEdge(2 + u, x, 1, 0);
          if (adj[v][u] != 0) ids[v][u] = mcf.addEdge(2 + v, x, 1, 0);
          ++x;
        }
        assert(x == 2 + N + N * (N - 1) / 2);
      }
      const res = mcf.solve(0, 1, N * (N - 1) / 2);
      debug {
        writeln("tof = ", mcf.tof, ", toc = ", mcf.toc);
      }
      assert(res);

      auto ans = new int[][](N, N);
      foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
        if (ids[u][v] != -1 && mcf.capa[ids[u][v]] == 0) ans[u][v] = 1;
        if (ids[v][u] != -1 && mcf.capa[ids[v][u]] == 0) ans[v][u] = 1;
        assert(ans[u][v] + ans[v][u] == 1);
      }
      foreach (u; 0 .. N) {
        foreach (v; 0 .. N) {
          write(ans[u][v]);
        }
        writeln();
      }
    }
  } catch (EOFException e) {
  }
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

class MaxFlow(Capa) {
  enum Capa wEPS = 0;
  enum Capa wINF = 10^^9;
  int n, m;
  int[][] g;
  int[] zu;
  Capa[] capa;
  Capa tof;
  int[] lev, see, que;
  this(int n) {
    this.n = n; m = 0; g = new int[][n]; zu = []; capa = [];
    lev = new int[n]; see = new int[n]; que = new int[n];
  }
  void addEdge(int u, int v, Capa w0, Capa w1 = 0) {
    g[u] ~= m; zu ~= v; capa ~= w0; ++m;
    g[v] ~= m; zu ~= u; capa ~= w1; ++m;
  }
  Capa augment(int src, int ink, Capa flo) {
    if (src == ink) return flo;
    foreach (i; g[src][see[src] .. $]) {
      if (capa[i] > wEPS && lev[src] < lev[zu[i]]) {
        Capa f = augment(zu[i], ink, min(flo, capa[i]));
        if (f > wEPS) { capa[i] -= f; capa[i ^ 1] += f; return f; }
      }
      ++see[src];
    }
    return 0;
  }
  bool dinic(int src, int ink, Capa flo = wINF) {
    for (tof = 0; tof + wEPS < flo; ) {
      int[] q;
      lev[] = -1;
     dinicBFS:
      for (lev[src] = 0, q ~= src; !q.empty; ) {
        int u = q.front; q.popFront;
        foreach (i; g[u]) {
          int v = zu[i];
          if (capa[i] > wEPS && lev[v] == -1) {
            lev[v] = lev[u] + 1; q ~= v;
            if (v == ink) break dinicBFS;
          }
        }
      }
      if (lev[ink] == -1) return false;
      see[] = 0;
      for (; ; ) {
        Capa f = augment(src, ink, flo - tof);
        if (f <= wEPS) break;
        tof += f;
      }
    }
    return true;
  }
}

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      const M = readInt();
      auto U = new int[M];
      auto V = new int[M];
      foreach (i; 0 .. M) {
        U[i] = readInt() - 1;
        V[i] = readInt() - 1;
      }

      auto ws = new int[N];
      auto ls = new int[N];
      foreach (i; 0 .. M) {
        ++ws[U[i]];
        ++ls[V[i]];
      }
      auto dp = new int[][](N + 1, N * (N - 1) / 2 + 1);
      auto prev = new int[][](N + 1, N * (N - 1) / 2 + 1);
      foreach (u; 0 .. N + 1) {
        dp[u][] = -1;
      }
      dp[0][0] = 0;
      foreach (u; 0 .. N) {
        foreach (a; 0 .. N * (N - 1) / 2 + 1) {
          if (dp[u][a] >= 0) {
            foreach (x; ws[u] .. (N - 1 - ls[u]) + 1) {
              if (a + x <= N * (N - 1) / 2) {
                if (chmax(dp[u + 1][a + x], dp[u][a] + x * (N - 1 - x))) {
                  prev[u + 1][a + x] = x;
                }
              }
            }
          }
        }
      }
      auto xs = new int[N];
      for (int u = N, a = N * (N - 1) / 2; u > 0; ) {
        const x = prev[u][a];
        --u;
        a -= x;
        xs[u] = x;
      }
      debug {
        writeln("xs = ", xs);
      }

      auto ans = new char[][](N, N);
      foreach (u; 0 .. N) {
        ans[u][] = '0';
      }
      auto ys = new int[N];
      auto zs = new int[N];
      foreach (u; 0 .. N) {
        ys[u] = xs[u];
        zs[u] = N - 1 - xs[u];
      }
      foreach (i; 0 .. M) {
        ans[U[i]][V[i]] = '1';
        --ys[U[i]];
        --zs[V[i]];
      }
      debug {
        writeln("ys = ", ys);
        writeln("zs = ", zs);
      }

      auto mf = new MaxFlow!int(2 + N + N);
      foreach (u; 0 .. N) {
        mf.addEdge(0, 2 + u, ys[u]);
        mf.addEdge(2 + N + u, 1, zs[u]);
      }
      auto ids = new int[][](N, N);
      foreach (u; 0 .. N) foreach (v; 0 .. N) {
        if (u != v && ans[u][v] == '0' && ans[v][u] == '0') {
          ids[u][v] = mf.m;
          mf.addEdge(2 + u, 2 + N + v, 1);
        } else {
          ids[u][v] = -1;
        }
      }
      const res = mf.dinic(0, 1, N * (N - 1) / 2 - M);
      assert(res);

      foreach (u; 0 .. N) foreach (v; 0 .. N) {
        if (u != v && ans[u][v] == '0' && ans[v][u] == '0') {
          if (mf.capa[ids[u][v]] == 0) {
            ans[u][v] = '1';
          }
        }
      }
      foreach (u; 0 .. N) {
        writeln(ans[u]);
      }
    }
  } catch (EOFException e) {
  }
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

class MinCostFlow(Capa, Cost, Capa CAPA_EPS = 0) {
  int n, m;
  int[][] g;
  int[] as, bs;
  Capa[] capa;
  Cost[] cost, pot;
  Capa tof;
  Cost toc;
  this(int n) {
    this.n = n; m = 0; g = new int[][n]; as = []; bs = []; capa = []; cost = [];
  }
  int addEdge(int u, int v, Capa w, Cost c) {
    debug {
      writeln("addEdge ", u, " ", v, " ", w, " ", c);
    }
    const i = m;
    g[u] ~= m; as ~= u; bs ~= v; capa ~= w; cost ~= c; ++m;
    g[v] ~= m; as ~= v; bs ~= u; capa ~= 0; cost ~= -c; ++m;
    return i;
  }
  bool solve(int source, int sink, Capa flow) {
    pot = new Cost[n];
    pot[] = 0;
    for (; ; ) {
      bool cont;
      foreach (u; 0 .. n) foreach (i; g[u]) if (capa[i] > CAPA_EPS) {
        const v = bs[i];
        if (pot[v] > pot[u] + cost[i]) {
          pot[v] = pot[u] + cost[i];
          cont = true;
        }
      }
      if (!cont) break;
    }
    auto dist = new Cost[n];
    auto prei = new int[n];
    auto vis = new bool[n];
    for (tof = 0, toc = 0; tof + CAPA_EPS < flow; ) {
      alias Entry = Tuple!(Cost, "c", int, "u");
      BinaryHeap!(Array!Entry, "a < b") que;
      dist[] = -1;
      prei[] = -1;
      vis[] = false;
      dist[source] = 0;
      prei[source] = -2;
      que.insert(Entry(0, source));
      for (; !que.empty(); ) {
        const c = que.front.c;
        const u = que.front.u;
        que.removeFront;
        if (vis[u]) continue;
        vis[u] = true;
        foreach (i; g[u]) if (capa[i] > CAPA_EPS) {
          const v = bs[i];
          const cc = c + cost[i] + pot[u] - pot[v];
          if (prei[v] == -1 || dist[v] > cc) {
            dist[v] = cc;
            prei[v] = i;
            que.insert(Entry(cc, v));
          }
        }
      }
      if (!vis[sink]) return false;
      Capa f = flow - tof;
      for (int v = sink; v != source; ) {
        const i = prei[v];
        if (f > capa[i]) f = capa[i];
        v = as[i];
      }
      for (int v = sink; v != source; ) {
        const i = prei[v];
        capa[i] -= f; capa[i ^ 1] += f;
        v = as[i];
      }
      tof += f;
      toc += f * (dist[sink] - pot[source] + pot[sink]);
      pot[] += dist[];
    }
    return true;
  }
}

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      const M = readInt();
      auto U = new int[M];
      auto V = new int[M];
      foreach (i; 0 .. M) {
        U[i] = readInt() - 1;
        V[i] = readInt() - 1;
      }

      auto adj = new int[][](N, N);
      foreach (u; 0 .. N) {
        adj[u][] = -1;
      }
      foreach (i; 0 .. M) {
        adj[U[i]][V[i]] = 1;
        adj[V[i]][U[i]] = 0;
      }

      auto mcf = new MinCostFlow!(int, long)(2 + N + N * (N - 1) / 2);
      auto ids = new int[][](N, N);
      foreach (u; 0 .. N) {
        // -d (N - 1 - d)
        foreach (d; 0 .. N - 1) {
          const diff = (-(d + 1) * (N - 1 - (d + 1))) - (-d * (N - 1 - d));
          mcf.addEdge(0, 2 + u, 1, diff);
          debug {
            writeln(u, " ", d, ": ", diff);
          }
        }
      }
      foreach (x; 2 + N .. 2 + N + N * (N - 1) / 2) {
        mcf.addEdge(x, 1, 1, 0);
      }
      foreach (u; 0 .. N) {
        ids[u][] = -1;
      }
      {
        int x = 2 + N;
        foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
          if (adj[u][v] != 0) ids[u][v] = mcf.addEdge(2 + u, x, 1, 0);
          if (adj[v][u] != 1) ids[v][u] = mcf.addEdge(2 + v, x, 1, 0);
          ++x;
        }
        assert(x == 2 + N + N * (N - 1) / 2);
      }
      const res = mcf.solve(0, 1, N * (N - 1) / 2);
      assert(res);

      auto ans = new int[][](N, N);
      foreach (u; 0 .. N) foreach (v; u + 1 .. N) {
        if (ids[u][v] != -1 && mcf.capa[ids[u][v]] == 0) ans[u][v] = 1;
        if (ids[v][u] != -1 && mcf.capa[ids[v][u]] == 0) ans[v][u] = 1;
        assert(ans[u][v] + ans[v][u] == 1);
      }
      foreach (u; 0 .. N) {
        foreach (v; 0 .. N) {
          write(ans[u][v]);
        }
        writeln();
      }
    }
  } catch (EOFException e) {
  }
}

import std.conv, std.functional, std.range, std.stdio, std.string;
import std.algorithm, std.array, std.bigint, std.bitmanip, std.complex, std.container, std.math, std.mathspecial, std.numeric, std.regex, std.typecons;
import core.bitop;

class EOFException : Throwable { this() { super("EOF"); } }
string[] tokens;
string readToken() { for (; tokens.empty; ) { if (stdin.eof) { throw new EOFException; } tokens = readln.split; } auto token = tokens.front; tokens.popFront; return token; }
int readInt() { return readToken.to!int; }
long readLong() { return readToken.to!long; }
real readReal() { return readToken.to!real; }

bool chmin(T)(ref T t, in T f) { if (t > f) { t = f; return true; } else { return false; } }
bool chmax(T)(ref T t, in T f) { if (t < f) { t = f; return true; } else { return false; } }

int binarySearch(alias pred, T)(in T[] as) { int lo = -1, hi = cast(int)(as.length); for (; lo + 1 < hi; ) { const mid = (lo + hi) >> 1; (unaryFun!pred(as[mid]) ? hi : lo) = mid; } return hi; }
int lowerBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a >= val)); }
int upperBound(T)(in T[] as, T val) { return as.binarySearch!(a => (a > val)); }

class MaxFlow(Capa) {
  enum Capa wEPS = 0;
  enum Capa wINF = 10^^9;
  int n, m;
  int[][] g;
  int[] zu;
  Capa[] capa;
  Capa tof;
  int[] lev, see, que;
  this(int n) {
    this.n = n; m = 0; g = new int[][n]; zu = []; capa = [];
    lev = new int[n]; see = new int[n]; que = new int[n];
  }
  void addEdge(int u, int v, Capa w0, Capa w1 = 0) {
    g[u] ~= m; zu ~= v; capa ~= w0; ++m;
    g[v] ~= m; zu ~= u; capa ~= w1; ++m;
  }
  Capa augment(int src, int ink, Capa flo) {
    if (src == ink) return flo;
    foreach (i; g[src][see[src] .. $]) {
      if (capa[i] > wEPS && lev[src] < lev[zu[i]]) {
        Capa f = augment(zu[i], ink, min(flo, capa[i]));
        if (f > wEPS) { capa[i] -= f; capa[i ^ 1] += f; return f; }
      }
      ++see[src];
    }
    return 0;
  }
  bool dinic(int src, int ink, Capa flo = wINF) {
    for (tof = 0; tof + wEPS < flo; ) {
      int[] q;
      lev[] = -1;
     dinicBFS:
      for (lev[src] = 0, q ~= src; !q.empty; ) {
        int u = q.front; q.popFront;
        foreach (i; g[u]) {
          int v = zu[i];
          if (capa[i] > wEPS && lev[v] == -1) {
            lev[v] = lev[u] + 1; q ~= v;
            if (v == ink) break dinicBFS;
          }
        }
      }
      if (lev[ink] == -1) return false;
      see[] = 0;
      for (; ; ) {
        Capa f = augment(src, ink, flo - tof);
        if (f <= wEPS) break;
        tof += f;
      }
    }
    return true;
  }
}

void main() {
  try {
    for (; ; ) {
      const N = readInt();
      const M = readInt();
      auto U = new int[M];
      auto V = new int[M];
      foreach (i; 0 .. M) {
        U[i] = readInt() - 1;
        V[i] = readInt() - 1;
      }

      auto ws = new int[N];
      auto ls = new int[N];
      foreach (i; 0 .. M) {
        ++ws[U[i]];
        ++ls[V[i]];
      }
      auto dp = new int[][](N + 1, N * (N - 1) / 2 + 1);
      auto prev = new int[][](N + 1, N * (N - 1) / 2 + 1);
      foreach (u; 0 .. N + 1) {
        dp[u][] = -1;
      }
      dp[0][0] = 0;
      foreach (u; 0 .. N) {
        foreach (a; 0 .. N * (N - 1) / 2 + 1) {
          if (dp[u][a] >= 0) {
            foreach (x; ws[u] .. (N - 1 - ls[u]) + 1) {
              if (a + x <= N * (N - 1) / 2) {
                if (chmax(dp[u + 1][a + x], dp[u][a] + x * (N - 1 - x))) {
                  prev[u + 1][a + x] = x;
                }
              }
            }
          }
        }
      }
      auto xs = new int[N];
      for (int u = N, a = N * (N - 1) / 2; u > 0; ) {
        const x = prev[u][a];
        --u;
        a -= x;
        xs[u] = x;
      }
      debug {
        writeln("xs = ", xs);
      }

      auto mf = new MaxFlow!int(2 + N + N);
      foreach (u; 0 .. N) {
        mf.addEdge(0, 2 + u, xs[u]);
        mf.addEdge(2 + N + u, 1, N - 1 - xs[u]);
      }
      auto ids = new int[][](N, N);
      foreach (u; 0 .. N) foreach (v; 0 .. N) {
        if (u != v) {
          ids[u][v] = mf.m;
          mf.addEdge(2 + u, 2 + N + v, 1);
        } else {
          ids[u][v] = -1;
        }
      }
      const res = mf.dinic(0, 1, N * (N - 1) / 2);
      assert(res);

      auto ans = new char[][](N, N);
      foreach (u; 0 .. N) {
        ans[u][] = '0';
      }
      foreach (u; 0 .. N) foreach (v; 0 .. N) {
        if (u != v) {
          if (mf.capa[ids[u][v]] == 0) {
            ans[u][v] = '1';
          }
        }
      }
      foreach (u; 0 .. N) {
        writeln(ans[u]);
      }
    }
  } catch (EOFException e) {
  }
}