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

typedef long long ll;
#define all(v) v.begin(),v.end()
#define X first
#define Y second
#define rep(x, y, z) for(ll (z) = (x); (z) < (y); (z)++)

int constexpr N = 5 * 1e3;
int constexpr MOD = 1e9 + 7;
int constexpr INF = 1e9;

vector<int> g[N], res;
bool mark[N], adj[N][N];
int dep[N], pa[N];

void dfs(int v, int d, int p) {
    mark[v] = true;
    dep[v] = d;
    pa[v] = p;
//    cerr << v << ' ' << dep[v] << '\n';
    for (auto u : g[v]) {
        if (!mark[u]) {
            dfs(u, d + 1, v);
            if (res[0] != -1) return;
        }
        else if (dep[v] - dep[u] >= 2) {
            int vv = v;
            res = {v};
            while (vv != u) {
                vv = pa[vv];
                res.push_back(vv);
            }
            return;
        }
    }
    res = {-1};
}
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int n;
    cin >> n;
    rep (0, n, i) {
        rep (0, n, j) {
            char c;
            cin >> c;
//            cerr << c << ' ';
            adj[i][j] = c - '0';
            if (c - '0') g[i].push_back(j);
        }
    }
    dfs(0, 0, -1);
    if (res[0] == -1) cout << -1;
    else {
        reverse(all(res));
        rotate(res.begin(), res.begin() + 1, res.end());
        deque<int> vs(all(res));
        int f = res.back(), v = res[1];
        vs.pop_back();
        while (vs.size() > 2) {
            if (adj[f][v]) {
                while (vs.front() != v) vs.pop_front();
            } else {
                while (vs.back() != v) vs.pop_back();
            }
            v = vs[0];
        }
        for (auto u : vs)
            cout << u + 1 << ' ';
        cout << f + 1;
    }
    return 0;
}


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

typedef long long ll;
#define all(v) v.begin(),v.end()
#define X first
#define Y second
#define rep(x, y, z) for(ll (z) = (x); (z) < (y); (z)++)

int constexpr N = 5 * 1e3;
int constexpr MOD = 1e9 + 7;
int constexpr INF = 1e9;

vector<int> g[N];
bool mark[N];
int dep[N], pa[N];

vector<int> dfs(int v, int d, int p) {

    stack<int> s;
    s.push(v);
    dep[v] = d;
    pa[v] = p;
    mark[v] = true;
    while (!s.empty()) {
        v = s.top();
        s.pop();
        for (auto u : g[v]) {
            if (!mark[u]) {
                s.push(u);
                dep[u] = dep[v] + 1;
                mark[u] = true;
                pa[u] = v;
            }
            else if (dep[v] - dep[u] >= 2) {
                return {pa[v], v, u};
            }
        }
    }
    return {-1};
}
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int n;
    cin >> n;
    rep (0, n, i) {
        rep (0, n, j) {
            char c;
            cin >> c;
//            cerr << c << ' ';
//            adj[i][j] = c - '0';
            if (c - '0') g[i].push_back(j);
        }
    }
    auto res = dfs(0, 0, -1);
    if (res[0] == -1) cout << -1;
    else
        for (auto v : res)
            cout << v + 1 << ' ';

    return 0;
}


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

typedef long long ll;
#define all(v) v.begin(),v.end()
#define X first
#define Y second
#define rep(x, y, z) for(ll (z) = (x); (z) < (y); (z)++)

int constexpr N = 5 * 1e3;
int constexpr MOD = 1e9 + 7;
int constexpr INF = 1e9;

vector<int> g[N];
bool mark[N];
int dep[N], pa[N];

vector<int> dfs(int v, int d, int p) {
    mark[v] = true;
    dep[v] = d;
    pa[v] = p;
    for (auto u : g[v]) {
        if (!mark[u]) {
            auto vec = dfs(u, d + 1, v);
            if (vec[0] != -1) return vec;
        }
        else if (dep[v] - dep[u] == 2) {
            return {v, u, pa[v]};
        }
    }
    return {-1, -1, -1};
}
int main() {
//    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int n;
    cin >> n;
    rep (0, n, i) {
        rep (0, n, j) {
            char c;
            scanf(" %c", &c);
//            adj[i][j] = c - '0';
            if (c - '0') g[i].push_back(j);
        }
    }
    auto res = dfs(0, 0, -1);
    if (res[0] == -1) cout << -1;
    else
        for (auto v : res)
            cout << v + 1 << ' ';

    return 0;
}


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

typedef long long ll;
#define all(v) v.begin(),v.end()
#define X first
#define Y second
#define rep(x, y, z) for(ll (z) = (x); (z) < (y); (z)++)

int constexpr N = 5 * 1e3;
int constexpr MOD = 1e9 + 7;
int constexpr INF = 1e9;

vector<int> g[N];
bool mark[N], adj[N][N];
int dep[N], pa[N];

vector<int> dfs(int v, int d, int p) {
    mark[v] = true;
    dep[v] = d;
    pa[v] = p;
//    cerr << v << ' ' << dep[v] << '\n';
    for (auto u : g[v]) {
        if (!mark[u]) {
            auto vec = dfs(u, d + 1, v);
            if (vec[0] != -1) return vec;
        }
        else if (dep[v] - dep[u] >= 2) {
            int vv = v;
            vector<int> res = {v};
            while (vv != u) {
                vv = pa[vv];
                res.push_back(vv);
            }
            return res;
        }
    }
    return {-1};
}
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int n;
    cin >> n;
    rep (0, n, i) {
        rep (0, n, j) {
            char c;
            cin >> c;
//            cerr << c << ' ';
            adj[i][j] = c - '0';
            if (c - '0') g[i].push_back(j);
        }
    }
    auto res = dfs(0, 0, -1);
    if (res[0] == -1) cout << -1;
    else {
        reverse(all(res));
        rotate(res.begin(), res.begin() + 1, res.end());
        deque<int> vs(all(res));
        int f = res.back(), v = res[1];
        vs.pop_back();
        while (vs.size() > 2) {
            if (adj[f][v]) {
                while (vs.front() != v) vs.pop_front();
            } else {
                while (vs.back() != v) vs.pop_back();
            }
            v = vs[0];
        }
        for (auto u : vs)
            cout << u + 1 << ' ';
        cout << f + 1;
    }
    return 0;
}


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

typedef long long ll;
#define all(v) v.begin(),v.end()
#define X first
#define Y second
#define rep(x, y, z) for(ll (z) = (x); (z) < (y); (z)++)

int constexpr N = 5 * 1e3;
int constexpr MOD = 1e9 + 7;
int constexpr INF = 1e9;

vector<int> g[N];
bool mark[N], col[N], adj[N][N];
tuple<int, int, int> dfs(int v, bool c, int p) {
    mark[v] = true;
    col[v] = c;

    for (auto u : g[v]) {
        if (!mark[u]) {
            auto [v1, v2, v3] = dfs(u, !c, v);
            if (v1 != -1) return {v1, v2, v3};
        }
        else if (col[u] == col[v]) {
            if (p != -1 && adj[u][p])
                return {u, p, v};
        }
    }
    return {-1, -1, -1};
}
int main() {
//    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int n;
    cin >> n;
    rep (0, n, i) {
        rep (0, n, j) {
            char c;
            scanf(" %c", &c);
            adj[i][j] = c - '0';
            if (c - '0') g[i].push_back(j);
        }
    }
    auto [v1, v2, v3] = dfs(0, 0, -1);
    if (v1 != -1) cout << v1 + 1 << ' ' << v2 + 1 << ' ' << v3 + 1;
    else cout << -1;
    return 0;
}


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

typedef long long ll;
#define all(v) v.begin(),v.end()
#define X first
#define Y second
#define rep(x, y, z) for(ll (z) = (x); (z) < (y); (z)++)

int constexpr N = 5 * 1e3;
int constexpr MOD = 1e9 + 7;
int constexpr INF = 1e9;

vector<int> g[N];
bool mark[N], col[N], adj[N][N];
tuple<int, int, int> dfs(int v, bool c, int p) {
    mark[v] = true;
    col[v] = c;

    for (auto u : g[v]) {
        if (!mark[u]) {
            auto [v1, v2, v3] = dfs(u, !c, v);
            if (v1 != -1) return {v1, v2, v3};
        }
        else if (col[u] == col[v]) {
            if (p != -1 && adj[u][p])
                return {u, v, p};
        }
    }
    return {-1, -1, -1};
}
int main() {
//    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int n;
    cin >> n;
    rep (0, n, i) {
        rep (0, n, j) {
            char c;
            scanf(" %c", &c);
            adj[i][j] = c - '0';
            if (c - '0') g[i].push_back(j);
        }
    }
    auto [v1, v2, v3] = dfs(0, 0, -1);
    if (v1 != -1) cout << v1 + 1 << ' ' << v2 + 1 << ' ' << v3 + 1;
    else cout << -1;
    return 0;
}


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

typedef long long ll;
#define all(v) v.begin(),v.end()
#define X first
#define Y second
#define rep(x, y, z) for(ll (z) = (x); (z) < (y); (z)++)

int constexpr N = 5 * 1e3;
int constexpr MOD = 1e9 + 7;
int constexpr INF = 1e9;

vector<int> g[N];
bool mark[N];
int dep[N], pa[N];

vector<int> dfs(int v, int d, int p) {

    stack<int> s;
    s.push(v);
    dep[v] = d;
    pa[v] = p;
    mark[v] = true;
    while (!s.empty()) {
        v = s.top();
        s.pop();
        for (auto u : g[v]) {
            if (!mark[u]) {
                s.push(u);
                dep[u] = dep[v] + 1;
                mark[u] = true;
                pa[u] = v;
            }
            else if (dep[v] - dep[u] == 2) {
                return {pa[v], v, u};
            }
        }
    }
    return {-1};
}
int main() {
//    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int n;
    cin >> n;
    rep (0, n, i) {
        rep (0, n, j) {
            char c;
            scanf(" %c", &c);
//            adj[i][j] = c - '0';
            if (c - '0') g[i].push_back(j);
        }
    }
    auto res = dfs(0, 0, -1);
    if (res[0] == -1) cout << -1;
    else
        for (auto v : res)
            cout << v + 1 << ' ';

    return 0;
}


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

typedef long long ll;
#define all(v) v.begin(),v.end()
#define X first
#define Y second
#define rep(x, y, z) for(ll (z) = (x); (z) < (y); (z)++)

int constexpr N = 5 * 1e3;
int constexpr MOD = 1e9 + 7;
int constexpr INF = 1e9;

int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int n;
    cin >> n;
    vector<vector<int>> g(n);
    vector<char> mark(n, false);
    vector<vector<char>> adj(n, vector<char>(n, false));

    rep (0, n, i) {
        rep (0, n, j) {
            char c;
            cin >> c;
//            cerr << c << ' ';
            adj[i][j] = c - '0';
            if (c - '0') g[i].push_back(j);
        }
    }
    function<tuple<int, int, int>(int, int)> dfs;
    dfs = [&](int v, int p) -> tuple<int, int, int> {
        mark[v] = true;

        for (auto u : g[v]) {
            if (p != -1 && adj[u][p]) {
                return {p, v, u};
            }
            if (!mark[u]) {
                int v1, v2, v3;
                tie(v1, v2, v3) = dfs(u, v);
                if (v1 != -1) return {v1, v2, v3};
            }
        }
        return {-1, -1, -1};
    };
    rep (0, n, i) {
        if (!mark[i]) {
            int v1, v2, v3;
            tie(v1, v2, v3) = dfs(i, -1);

            if (v1 != -1) return cout << v1 + 1 << ' ' << v2 + 1 << ' ' << v3 + 1, 0;
        }
    }
    cout << -1;
    return 0;
}


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

typedef long long ll;
#define all(v) v.begin(),v.end()
#define X first
#define Y second
#define rep(x, y, z) for(ll (z) = (x); (z) < (y); (z)++)

int constexpr N = 5 * 1e3;
int constexpr MOD = 1e9 + 7;
int constexpr INF = 1e9;

bool adj[N][N];
vector<int> g[N];

int main() {
//    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int n;
    cin >> n;
    rep (0, n, i) {
        rep (0, n, j) {
            char c;
            scanf(" %c", &c);
            if (c - '0') g[i].push_back(j);
        }
    }
    rep (0, n, i) {
        vector<char> mark(n, false);
        for (auto u : g[i]) {
            mark[u] = true;
        }
        for (auto u : g[i])
            for (auto v : g[u]) {
                if (!mark[v]) return cout << i + 1 << ' ' << u + 1 << ' ' << v + 1, 0;
                mark[v] = true;
            }

    }
    cout << -1;
    return 0;
}


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

typedef long long ll;
#define all(v) v.begin(),v.end()
#define X first
#define Y second
#define rep(x, y, z) for(ll (z) = (x); (z) < (y); (z)++)

int constexpr N = 5 * 1e3;
int constexpr MOD = 1e9 + 7;
int constexpr INF = 1e9;

vector<int> g[N];
bool mark[N], adj[N][N];

int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int n;
    cin >> n;
    rep (0, n, i) {
        rep (0, n, j) {
            char c;
            cin >> c;
//            cerr << c << ' ';
            adj[i][j] = c - '0';
            if (c - '0') g[i].push_back(j);
        }
    }
    function<tuple<int, int, int>(int, int)> dfs;
    dfs = [&](int v, int p) -> tuple<int, int, int> {
        mark[v] = true;

        for (auto u : g[v]) {
            if (p != -1 && adj[u][p]) {
                return {p, v, u};
            }
            if (!mark[u]) {
                int v1, v2, v3;
                tie(v1, v2, v3) = dfs(u, v);
                if (v1 != -1) return {v1, v2, v3};
            }
        }
        return {-1, -1, -1};
    };
    rep (0, n, i) {
        if (!mark[i]) {
            int v1, v2, v3;
            tie(v1, v2, v3) = dfs(i, -1);

            if (v1 != -1) return cout << v1 + 1 << ' ' << v2 + 1 << ' ' << v3 + 1, 0;
        }
    }
    cout << -1;
    return 0;
}


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

typedef long long ll;
#define all(v) v.begin(),v.end()
#define X first
#define Y second
#define rep(x, y, z) for(ll (z) = (x); (z) < (y); (z)++)

int constexpr N = 5 * 1e3;
int constexpr MOD = 1e9 + 7;
int constexpr INF = 1e9;

vector<int> g[N];
bool mark[N];
int dep[N], pa[N];

vector<int> dfs(int v, int d, int p) {

    stack<int> s;
    s.push(v);
    dep[v] = d;
    pa[v] = p;
    mark[v] = true;
    while (!s.empty()) {
        v = s.top();
        s.pop();
        for (auto u : g[v]) {
            if (!mark[u]) {
                s.push(u);
                dep[u] = dep[v] + 1;
                mark[u] = true;
                pa[u] = v;
            }
            else if (dep[v] - dep[u] == 2) {
                return {pa[v], v, u};
            }
        }
    }
    return {-1};
}
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int n;
    cin >> n;
    rep (0, n, i) {
        rep (0, n, j) {
            char c;
            cin >> c;
//            cerr << c << ' ';
//            adj[i][j] = c - '0';
            if (c - '0') g[i].push_back(j);
        }
    }
    auto res = dfs(0, 0, -1);
    if (res[0] == -1) cout << -1;
    else
        for (auto v : res)
            cout << v + 1 << ' ';

    return 0;
}


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

typedef long long ll;
#define all(v) v.begin(),v.end()
#define X first
#define Y second
#define rep(x, y, z) for(ll (z) = (x); (z) < (y); (z)++)

int constexpr N = 5 * 1e3;
int constexpr MOD = 1e9 + 7;
int constexpr INF = 1e9;

bool adj[N][N];
int main() {
//    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int n;
    cin >> n;
    rep (0, n, i) {
        rep (0, n, j) {
            char c;
            scanf(" %c", &c);
            adj[i][j] = c - '0';
        }
    }
    rep (0, n, i) {
        vector<int> zer, one;
        rep (0, n, j) {
            (adj[i][j] ? one : zer).push_back(j);
        }
        for (auto o : one) {
            for (auto z : zer) {
                if (adj[o][z]) {
                    cout << i + 1 << ' ' << o + 1 << ' ' << z + 1;
                    return 0;
                }
            }
        }
    }
    cout << -1;
    return 0;
}


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

typedef long long ll;
#define all(v) v.begin(),v.end()
#define X first
#define Y second
#define rep(x, y, z) for(ll (z) = (x); (z) < (y); (z)++)

int constexpr N = 5 * 1e3;
int constexpr MOD = 1e9 + 7;
int constexpr INF = 1e9;

vector<int> g[N];
bool mark[N];
int dep[N], pa[N];

vector<int> dfs(int v, int d, int p) {

    stack<int> s;
    s.push(v);
    dep[v] = d;
    pa[v] = p;
    mark[v] = true;
    while (!s.empty()) {
        v = s.top();
        s.pop();
        for (auto u : g[v]) {
            if (!mark[u]) {
                s.push(u);
                dep[u] = dep[v] + 1;
                mark[u] = true;
                pa[u] = v;
            }
            else if (dep[v] - dep[u] == 2) {
                return {pa[v], v, u};
            }
        }
    }
    return {-1};
}
int main() {
//    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int n;
    cin >> n;
    rep (0, n, i) {
        rep (0, n, j) {
            char c;
            scanf(" %c", &c);
//            adj[i][j] = c - '0';
            if (c - '0') g[i].push_back(j);
        }
    }
    auto res = dfs(0, 0, -1);
    if (res[0] == -1) printf("-1");
    else
        for (auto v : res)
            printf("%d ", v + 1);

    return 0;
}


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

typedef long long ll;
#define all(v) v.begin(),v.end()
#define X first
#define Y second
#define rep(x, y, z) for(ll (z) = (x); (z) < (y); (z)++)

int constexpr N = 5 * 1e3;
int constexpr MOD = 1e9 + 7;
int constexpr INF = 1e9;

vector<int> g[N];
bool mark[N], adj[N][N];

tuple<int, int, int> dfs(int v, int p) {
    mark[v] = true;
//    cerr << v << ' ' << dep[v] << '\n';
    for (auto u : g[v]) {
        if (p != -1 && adj[u][p]) {
            return {p, v, u};
        }
        if (!mark[u]) {
            int v1, v2, v3;
            tie(v1, v2, v3) = dfs(u, v);
            if (v1 != -1) return {v1, v2, v3};
        }
    }
    return {-1, -1, -1};
}
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    int n;
    cin >> n;
    rep (0, n, i) {
        rep (0, n, j) {
            char c;
            cin >> c;
//            cerr << c << ' ';
            adj[i][j] = c - '0';
            if (c - '0') g[i].push_back(j);
        }
    }
    int v1, v2, v3;
    tie(v1, v2, v3) = dfs(0, -1);
    if (v1 == -1) cout << -1;
    else cout << v1 + 1 << ' ' << v2 + 1 << ' ' << v3 + 1;
//    else {
//        reverse(all(res));
//        rotate(res.begin(), res.begin() + 1, res.end());
//        deque<int> vs(all(res));
//        int f = res.back(), v = res[1];
//        vs.pop_back();
//        while (vs.size() > 2) {
//            if (adj[f][v]) {
//                while (vs.front() != v) vs.pop_front();
//            } else {
//                while (vs.back() != v) vs.pop_back();
//            }
//            v = vs[0];
//        }
//        for (auto u : vs)
//            cout << u + 1 << ' ';
//        cout << f + 1;
//    }
    return 0;
}


#pragma GCC optimize("O3")
#include <bits/stdc++.h>
using namespace std;
#define boost ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define rando mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define fi first
#define se second
#define debug(x) cerr << " - " << #x << ": " << x << endl;
#define debugs(x, y) cerr << " - " << #x << ": " << x << " " << #y << ": " << y << endl;
#define debugii(x) cerr << " - " << #x << ": " << x.fi<<","<<x.se << endl;
#define sep() cerr << "--------------------" << endl;
#define all(x) (x).begin(),(x).end()
#define sz(x) (ll)x.size()
#define ld long double
#define ll long long
//#define int ll
#define ii pair<int,int>
#define v vector<int>
#define vii vector<ii>
#define vv vector<vector<int> >
#define mp make_pair
#define INF 1000000000
#define pb push_back
#define EPS 1e-9
const int MOD = 1000000007; // 998244353
bool tab[5005][5005];
void solve(v vec){
    if(sz(vec)<=2)return;
    int node=vec[0];
    v in,out;
    for (int i = 1; i < sz(vec); ++i)
    {
        if(tab[node][vec[i]])in.pb(vec[i]);
        else out.pb(vec[i]);
    }
    for(auto a:in)
        for(auto b:out)
            if(tab[a][b]){
                cout<<node+1<<" "<<a+1<<" "<<b+1<<"\n";
                exit(0);
            }
    solve(in),solve(out);
}
int32_t main(){
    boost;
    //freopen(".in","r",stdin);
    int n;
    char a;
    v h;
    cin>>n;
    for (int i = 0; i < n; ++i){
        for (int j = 0; j < n; ++j){
            cin>>a;
            tab[i][j]=(a=='1');
        }
        h.pb(i);
    }
    solve(h);
    cout<<-1<<"\n";
    return 0;
}

//do smth instead of nothing and stay organized
//long long
//array bounds
//special cases
//binary search


#pragma GCC optimize("O3")
#include <bits/stdc++.h>
using namespace std;
#define boost ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define rando mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define fi first
#define se second
#define debug(x) cerr << " - " << #x << ": " << x << endl;
#define debugs(x, y) cerr << " - " << #x << ": " << x << " " << #y << ": " << y << endl;
#define debugii(x) cerr << " - " << #x << ": " << x.fi<<","<<x.se << endl;
#define sep() cerr << "--------------------" << endl;
#define all(x) (x).begin(),(x).end()
#define sz(x) (ll)x.size()
#define ld long double
#define ll long long
//#define int ll
#define ii pair<int,int>
#define v vector<int>
#define vii vector<ii>
#define vv vector<vector<int> >
#define mp make_pair
#define INF 1000000000
#define pb push_back
#define EPS 1e-9
const int MOD = 1000000007; // 998244353
bool vis[5005],tab[5005][5005];
char a;
v vec[5005];
int n;
void dfs(int node,int d,int d_p,int p){
    if(!d){
        for(auto it:vec[node])
            if(it!=d_p && tab[it][d_p]){
                cout<<p+1<<" "<<node+1<<" "<<it+1<<"\n";
                exit(0);
            }
        return ;
    }
    for(auto it:vec[node]){
        if(it!=p)dfs(it,d-1,node,p);
    }
}
int32_t main(){
    boost;
    //freopen(".in","r",stdin);
    cin>>n;
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j){
            cin>>a;
            tab[i][j]=(a=='1');
            if(a=='1')vec[i].pb(j);
        }
    for (int i = 0; i < n; ++i)
        dfs(i,1,i,i);
    cout<<"-1\n";
    return 0;
}

//do smth instead of nothing and stay organized
//long long
//array bounds
//special cases
//binary search


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

typedef complex<int> point;
typedef long long int lli;
typedef long double ld;
#define pii pair<int,int>
#define lasB(b) (b&(-b))
#define pld pair<ld,ld>
#define mod 1000000007
#define PI acos(-1.0)
#define PB push_back
#define N     5003
#define EPS (1e-8)
#define ss substr
#define S second
#define IM image
#define F first
#define RE real
#define B begin
#define E end

int n,mat[N][N],vis[N];

int dfs(int x,int l)
{
    vis[x]=1;
    for(int j=1;j<=n;j++)
    {
        if(mat[x][j])
        {
            if(mat[j][l] && x!=l && x!=j &&l!=j)
            {
                cout<<l<<" "<<x<<" "<<j;
                exit(0);
            }
            if(!vis[j])dfs(j,x);
        }
    }
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n;
    char aux;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            cin>>aux;
            mat[i][j]=aux-'0';
        }
    for(int i=1;i<=n;i++)
        if(!vis[i])
            dfs(i,0);
    cout<<-1,0;
    return 0;
}


#include <iostream>
#include <vector>
#include <cstdio>

using namespace std;

int n;

vector<string> all;

int main()
{
    scanf("%d" ,&n);

    all.resize(n+5);

    for(int i=0;i<n;i++)cin>>all[i];

    for(int i=0;i<n;i++)
    {
        int cap=0;
        for(auto x : all[i])
        {
            if(x=='1')
            {
                cap=1;
                break;
            }
        }

            for(int y=0;y<n;y++)
            {
                if(all[y][i]=='1')
                {

                    cap++;
                    break;
                }

            }

        if(cap==2)
        {
            for(int j=0;j<n;j++)
            {
                if(all[i][j]=='1')
                {
                    for(int k=0;k<n;k++)
                    {
                        if(all[j][k]=='1')
                        {

                            if(all[k][i]=='1')
                            {
                                cout<<i+1<<" "<< j+1<<" "<<k+1;
                                return 0;
                            }

                        }
                    }
                }
            }
        }
    }
    cout<<-1;
    return 0;
}


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

typedef complex<int> point;
typedef long long int lli;
typedef long double ld;
#define pii pair<int,int>
#define lasB(b) (b&(-b))
#define pld pair<ld,ld>
#define mod 1000000007
#define PI acos(-1.0)
#define PB push_back
#define N     5003
#define EPS (1e-8)
#define ss substr
#define S second
#define IM image
#define F first
#define RE real
#define B begin
#define E end

int n,a1,a2,a3,t;
bool ok;

int fat[N],sz[N],vis[N];

vector<int> adj[N],adj2[N];

int fin(int x)
{
    if(fat[x]!=x)
        return fat[x]=fin(fat[x]);
    return fat[x];
}

void unio(int a , int b)
{
    int aa = fin(a);
    int bb = fin(b);
    if(aa==bb)
    {
        t++;
        for(auto u : adj[b])
            vis[u]=t;
        for(auto u : adj2[a])
        {
            if(vis[u]==t)
            {
                a1=a;
                a2=b;
                a3=u;
                ok=1;
            }
        }
        return;
    }
    else if(sz[aa]>=sz[bb])
    {
        fat[bb]=aa;
        sz[aa]=max(sz[aa],sz[bb]+1);
    }
    else
    {
        fat[aa]=bb;
        sz[bb]=max(sz[bb],sz[aa]+1);
    }
    adj[a].PB(b);
    adj2[b].PB(a);
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    for(int i=1;i<N;i++)
        fat[i]=i;
    cin>>n;
    char aux;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            cin>>aux;
            if(aux=='1'&&!ok)
                unio(i,j);
        }
    if(ok)return cout<<a1<<" "<<a2<<" "<<a3,0;
    cout<<-1,0;
    return 0;
}


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

typedef complex<int> point;
typedef long long int lli;
typedef long double ld;
#define pii pair<int,int>
#define lasB(b) (b&(-b))
#define pld pair<ld,ld>
#define mod 1000000007
#define PI acos(-1.0)
#define PB push_back
#define N     5003
#define EPS (1e-8)
#define ss substr
#define S second
#define IM image
#define F first
#define RE real
#define B begin
#define E end

int n,a1,a2,a3,t;
bool ok;

int fat[N],sz[N],vis[N];

vector<int> adj[N],adj2[N];

int fin(int x)
{
    if(fat[x]!=x)
        return fat[x]=fin(fat[x]);
    return fat[x];
}

void unio(int a , int b)
{
    int aa = fin(a);
    int bb = fin(b);
    if(aa==bb)
    {
        adj[a].PB(b);
        adj2[b].PB(a);
        t++;
        for(auto u : adj[b])
            vis[u]=t;
        for(auto u : adj2[a])
        {
            if(vis[u]==t)
            {
                a1=a;
                a2=b;
                a3=u;
                ok=1;
            }
        }
        return;
    }
    else if(sz[aa]>=sz[bb])
    {
        fat[bb]=aa;
        sz[aa]=max(sz[aa],sz[bb]+1);
    }
    else
    {
        fat[aa]=bb;
        sz[bb]=max(sz[bb],sz[aa]+1);
    }
    adj[a].PB(b);
    adj2[b].PB(a);
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    for(int i=1;i<N;i++)
        fat[i]=i;
    cin>>n;
    char aux;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            cin>>aux;
            if(aux=='1'&&!ok)
                unio(i,j);
        }
    if(ok)return cout<<a1<<" "<<a2<<" "<<a3,0;
    cout<<-1,0;
    return 0;
}


#include <iostream>
#include <vector>
#include <cstdio>

using namespace std;

int n,cool=0,start;
vector<int> adj[5005];

int dfs(int stat,int dist,int mid){

    if(cool)return 0;
    if(dist==1)mid=stat;

    if(dist<2)
    {
        for(auto o : adj[stat])dfs(o,dist+1,mid);
    }
    if(dist==2)
    {
        for(auto o : adj[stat])
        {
            if(o==start){
                cout<<start<<" "<<mid<<" "<<stat<<"\n";
                cool=1;
                break;
            }
        }
    }
}

int main()
{
    scanf("%d" ,&n);

    for(int i=1;i<=n;i++)
    {
        string temp;cin>>temp;
        for(int o=0;o<n;o++)
        {
            if(temp[o]=='1')adj[i].push_back(o+1);
        }
    }

    for(int i=1;i<=n;i++)
    {
        start=i;
        dfs(i,0,0);
    }

    if(!cool)cout<<-1;

    return 0;
}


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

typedef complex<int> point;
typedef long long int lli;
typedef long double ld;
#define pii pair<int,int>
#define lasB(b) (b&(-b))
#define pld pair<ld,ld>
#define mod 1000000007
#define PI acos(-1.0)
#define PB push_back
#define N     5003
#define EPS (1e-8)
#define ss substr
#define S second
#define IM image
#define F first
#define RE real
#define B begin
#define E end

int n,a1,a2,a3;
bool ok;

int fat[N],sz[N];

vector<int> adj[N],adj2[N];

int fin(int x)
{
    if(fat[x]!=x)
        return fin(fat[x]);
    return fat[x];
}

void unio(int a , int b)
{
    int aa = fin(a);
    int bb = fin(b);
    if(aa==bb)
    {
        map<int,int> two;
        for(auto u : adj[b])
            two[u]=1;
        for(auto u : adj2[a])
        {
            if(two[u])
            {
                a1=a;
                a2=b;
                a3=u;
                ok=1;
            }
        }
        return ;
    }
    else if(sz[aa]>=sz[bb])
    {
        fat[bb]=aa;
        sz[aa]=max(sz[aa],sz[bb]+1);
    }
    else
    {
        fat[aa]=bb;
        sz[bb]=max(sz[bb],sz[aa]+1);
    }
    adj[a].PB(b);
    adj2[b].PB(a);
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    for(int i=1;i<N;i++)
        fat[i]=i;
    cin>>n;
    char aux;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            cin>>aux;
            if(aux=='1'&&!ok)
                unio(i,j);
        }
    if(ok)return cout<<a1<<" "<<a2<<" "<<a3,0;
    cout<<-1,0;
    return 0;
}


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

typedef complex<int> point;
typedef long long int lli;
typedef long double ld;
#define pii pair<int,int>
#define lasB(b) (b&(-b))
#define pld pair<ld,ld>
#define mod 1000000007
#define PI acos(-1.0)
#define PB push_back
#define N     5003
#define EPS (1e-8)
#define ss substr
#define S second
#define IM image
#define F first
#define RE real
#define B begin
#define E end

int n,a1,a2,a3;
bool ok;

int fat[N],sz[N];

vector<int> adj[N],adj2[N];

int fin(int x)
{
    if(fat[x]!=x)
        return fin(fat[x]);
    return fat[x];
}

void unio(int a , int b)
{
    int aa = fin(a);
    int bb = fin(b);
    if(aa==bb)
    {
        map<int,int> two;
        for(auto u : adj[b])
            two[u]=1;
        for(auto u : adj2[a])
        {
            if(two[u])
            {
                a1=a;
                a2=u;
                a3=b;
                ok=1;
            }
        }
        return ;
    }
    else if(sz[aa]>=sz[bb])
    {
        fat[bb]=aa;
        sz[aa]=max(sz[aa],sz[bb]+1);
    }
    else
    {
        fat[aa]=bb;
        sz[bb]=max(sz[bb],sz[aa]+1);
    }
    adj[a].PB(b);
    adj2[b].PB(a);
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    for(int i=1;i<N;i++)
        fat[i]=i;
    cin>>n;
    char aux;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            cin>>aux;
            if(aux=='1'&&!ok)
                unio(i,j);
        }
    if(ok)return cout<<a1<<" "<<a2<<" "<<a3,0;
    cout<<-1,0;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
bool dfs(int node,int pere,vector<vector<int>>& adj,vector<bool>& vu,vector<bool>& path,deque<int>& loop){
  vu[node] = true;
  path[node] = true;
  loop.push_back(node);
  for(int i : adj[node]){
    if(i == pere) continue;
    if(path[i]){
      loop.push_back(i);
      return true;
    }
    if(vu[i]) return false;
    if(dfs(i,node,adj,vu,path,loop)) return true;
  }
  loop.pop_back();
  path[node] = false;
  return false;
}
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n;
  cin >> n;
  string s;
  vector<vector<bool>> m(n,vector<bool>(n));
  vector<vector<int>> adj(n);
  for(int i = 0; i < n; ++i){
    cin >> s;
    for(int j = 0; j < n; ++j){
      if(s[j] == '1'){
        m[i][j] = true;
	adj[i].push_back(j);
      }
    }
  }
  vector<bool> vu(n),path(n);
  deque<int> loop;
  if(dfs(0,-1,adj,vu,path,loop)){
    while(!loop.empty() and loop.front() != loop.back()) loop.pop_front();
    while(loop.size() > 4){
      int a = loop[0],b = loop[1],c = loop[2];
      if(m[c][a]){
        cout << a+1 << ' ' << b+1 << ' ' << c+1;
	return 0;
      }
      loop.pop_front();
      loop.pop_front();
      loop.pop_front();
      loop.push_front(c);
      loop.push_front(a);
    }
    int a = loop[0],b = loop[1],c = loop[2];
    cout << a+1 << ' ' << b+1 << ' ' << c+1;
  }
  else cout << -1;
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
bool dfs(int node,vector<vector<int>>& adj,vector<bool>& vu,vector<bool>& path,deque<int>& loop){
  vu[node] = true;
  path[node] = true;
  loop.push_back(node);
  for(int i : adj[node]){
    if(path[i]){
      loop.push_back(i);
      return true;
    }
    if(vu[i]) continue;
    if(dfs(i,adj,vu,path,loop)) return true;
  }
  loop.pop_back();
  path[node] = false;
  return false;
}
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n;
  cin >> n;
  string s;
  vector<vector<bool>> m(n,vector<bool>(n));
  vector<vector<int>> adj(n);
  for(int i = 0; i < n; ++i){
    cin >> s;
    for(int j = 0; j < n; ++j){
      if(s[j] == '1'){
        m[i][j] = true;
	adj[i].push_back(j);
      }
    }
  }
  vector<bool> vu(n),path(n);
  deque<int> loop;
  if(dfs(0,adj,vu,path,loop)){
    while(!loop.empty() and loop.front() != loop.back()) loop.pop_front();
    loop.pop_back();
    while(loop.size() > 3){
      int a = loop[0],b = loop[1],c = loop[2];
      if(m[c][a]){
        cout << a+1 << ' ' << b+1 << ' ' << c+1;
	return 0;
      }
      loop.pop_front();
      loop[0] = a;
    }
    int a = loop[0],b = loop[1],c = loop[2];
    cout << a+1 << ' ' << b+1 << ' ' << c+1;
  }
  else cout << -1;
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n;
  cin >> n;
  string s;
  vector<vector<bool>> m(n,vector<bool>(n));
  vector<vector<int>> adj(n),prev(n);
  for(int i = 0; i < n; ++i){
    cin >> s;
    for(int j = 0; j < n; ++j){
      if(s[j] == '1'){
        m[i][j] = true;
        adj[i].push_back(j);
        prev[j].push_back(i);
      }
    }
  }
  for(int i = 0; i < n; ++i){
    for(int j : adj[i]){
      for(int k : prev[i]){
        if(m[j][k]){
	  cout << i+1 << ' ' << j+1 << ' ' << k+1;
	  return 0;
	}
      }
    }
  }
  cout << -1;
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n;
  cin >> n;
  string s;
  vector<vector<bool>> m(n,vector<bool>(n));
  for(int i = 0; i < n; ++i){
    cin >> s;
    for(int j = 0; j < n; ++j){
      if(s[j] == '1') m[i][j] = true;
    }
  }
  for(int i = 0; i < n; ++i){
    for(int j = 0; j < n; ++j){
      if(i == j or !m[j][i]) continue;
      for(int k = 0; k <n; ++k){
        if(k == i or k == j) continue;
        if(m[i][k] and m[k][j]){
	  cout << i+1 << ' ' << k+1 << ' ' << j+1;
	  return 0;
	}
      }
    }
  }
  cout << -1;
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
bool dfs(int node,int pere,vector<vector<int>>& adj,vector<bool>& vu,vector<bool>& path,deque<int>& loop){
  vu[node] = true;
  path[node] = true;
  loop.push_back(node);
  for(int i : adj[node]){
    if(i == pere) continue;
    if(path[i]){
      loop.push_back(i);
      return true;
    }
    if(vu[i]) continue;
    if(dfs(i,node,adj,vu,path,loop)) return true;
  }
  loop.pop_back();
  path[node] = false;
  return false;
}
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n;
  cin >> n;
  string s;
  vector<vector<bool>> m(n,vector<bool>(n));
  vector<vector<int>> adj(n);
  for(int i = 0; i < n; ++i){
    cin >> s;
    for(int j = 0; j < n; ++j){
      if(s[j] == '1'){
        m[i][j] = true;
	adj[i].push_back(j);
      }
    }
  }
  vector<bool> vu(n),path(n);
  deque<int> loop;
  if(dfs(0,-1,adj,vu,path,loop)){
    while(!loop.empty() and loop.front() != loop.back()) loop.pop_front();
    loop.pop_back();
    while(loop.size() > 3){
      int a = loop[0],b = loop[1],c = loop[2];
      if(m[c][a]){
        cout << a+1 << ' ' << b+1 << ' ' << c+1;
	return 0;
      }
      loop.pop_front();
      loop[0] = a;
    }
    int a = loop[0],b = loop[1],c = loop[2];
    cout << a+1 << ' ' << b+1 << ' ' << c+1;
  }
  else cout << -1;
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
bool dfs(int node,vector<vector<int>>& adj,vector<bool>& vu,vector<bool>& path,deque<int>& loop){
  vu[node] = true;
  path[node] = true;
  loop.push_back(node);
  for(int i : adj[node]){
    if(path[i]){
      loop.push_back(i);
      return true;
    }
    if(vu[i]) continue;
    if(dfs(i,adj,vu,path,loop)) return true;
  }
  loop.pop_back();
  path[node] = false;
  return false;
}
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n;
  cin >> n;
  string s;
  vector<vector<bool>> m(n,vector<bool>(n));
  vector<vector<int>> adj(n);
  for(int i = 0; i < n; ++i){
    cin >> s;
    for(int j = 0; j < n; ++j){
      if(s[j] == '1'){
        m[i][j] = true;
	adj[i].push_back(j);
      }
    }
  }
  vector<bool> vu(n),path(n);
  deque<int> loop;
  for(int i = 0; i < n; ++i){
    if(!vu[i]){
      if(dfs(i,adj,vu,path,loop)){
        while(loop.front() != loop.back()) loop.pop_front();
        loop.pop_back();
        while(loop.size() > 3){
          int a = loop[0],b = loop[1],c = loop[2];
          if(m[c][a]){
            cout << a+1 << ' ' << b+1 << ' ' << c+1;
	    return 0;
          }
          loop.pop_front();
          loop[0] = a;
        }
        int a = loop[0],b = loop[1],c = loop[2];
        cout << a+1 << ' ' << b+1 << ' ' << c+1;
        return 0;
      }
    }
  }
  cout << -1;
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n;
  cin >> n;
  vector<string> vs(n);
  for(int i = 0; i < n; ++i) cin >> vs[i];
  for(int i = 0; i < n; ++i){
    for(int j = 0; j < n; ++j){
      if(i == j) continue;
      if(vs[j][i] == '0') continue;
      for(int k = 0; k <n; ++k){
        if(k == i or k == j) continue;
        if(vs[i][k] == '1' and vs[k][j] == '1'){
	  cout << i+1 << ' ' << k+1 << ' ' << j+1;
	  return 0;
	}
      }
    }
  }
  cout << -1;
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n;
  cin >> n;
  string s;
  vector<vector<bool>> m(n,vector<bool>(n));
  vector<vector<int>> adj(n),prev(n);
  for(int i = 0; i < n; ++i){
    cin >> s;
    for(int j = 0; j < n; ++j){
      if(s[j] == '1'){
        m[i][j] = true;
        adj[i].push_back(j);
        prev[j].push_back(i);
      }
    }
  }
  vector<bool> vu(n);
  for(int i = 0; i < n; ++i){
    for(int j : adj[i]){
      if(vu[j]) continue;
      for(int k : prev[i]){
        if(vu[k]) continue;
        if(m[j][k]){
	  cout << i+1 << ' ' << j+1 << ' ' << k+1;
	  return 0;
	}
      }
    }
    vu[i] = true;
  }
  cout << -1;
  return 0;
}


#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
#define int long long
#define FI first
#define SE second
#define all(o) o.begin(), o.end()
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0)
#define SZ(x) ((int)(x).size())
#define PB push_back
#define PF push_front
#define MP make_pair
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pii> vii;
typedef long double ld;
typedef long long ll;
int gcd(int x,int y){ return (!y ? x : gcd(y, x%y)); }
int power(int x, int y) { return (!y ? 1 : power(x, y / 2) * power(x, y / 2) * (y % 2 ? x : 1)); }
const int MAXN=5e3+100,MOD=1e9+7;
int mod(int x) { return (x % MOD + MOD) % MOD; }
ll n,k,ans,m;
bool cycle;
string s;
vi g[MAXN];
int visited[MAXN],p[MAXN];
void dfs(int d){
    visited[d]=1;
    for(int u:g[d]){
        if(!visited[u]){
            p[u]=d;
            dfs(u);
        }
        else if(u==p[p[d]] && visited[u]==1 && !cycle ){
            cycle=true;
            cout<<p[p[d]]<<" "<<p[d]<<" "<<d<<" ";
            return;
        }
    }
    visited[d]=2;
}
void MAIN(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>s;
        s=" "+s;
        for(int j=1;j<=n;j++){
            char ch=s[j];
            if(ch=='1')g[i].PB(j);
        }
    }
    cycle=false;
    for(int i=1;i<=n;i++){
        if(cycle)break;
        //memset(visited,0,sizeof(visited));
        dfs(i);
    }
    if(!cycle)cout<<-1;
}
int32_t main(){
    IOS;
    int t;
    //cin>>t;
    t=1;
    while(t--)MAIN();
}


#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
#define int long long
#define FI first
#define SE second
#define all(o) o.begin(), o.end()
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0)
#define SZ(x) ((int)(x).size())
#define PB push_back
#define PF push_front
#define MP make_pair
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pii> vii;
typedef long double ld;
typedef long long ll;
int gcd(int x,int y){ return (!y ? x : gcd(y, x%y)); }
int power(int x, int y) { return (!y ? 1 : power(x, y / 2) * power(x, y / 2) * (y % 2 ? x : 1)); }
const int MAXN=5e3+100,MOD=1e9+7;
int mod(int x) { return (x % MOD + MOD) % MOD; }
ll n,k,ans,m;
bool cycle;
string s;
vi g[MAXN];
int visited[MAXN],p[MAXN];
void dfs(int d){
    visited[d]=1;
    for(int u:g[d]){
        if(!visited[u]){
            p[u]=d;
            dfs(u);
        }
        else if(u==p[p[d]] && visited[u]==1 && !cycle ){
            cycle=true;
            cout<<p[p[d]]<<" "<<p[d]<<" "<<d<<" ";
            return;
        }
    }
    visited[d]=2;
}
void MAIN(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>s;
        s=" "+s;
        for(int j=1;j<=n;j++){
            char ch=s[j];
            if(ch=='1')g[i].PB(j);
        }
    }
    cycle=false;
    for(int i=1;i<=n;i++){
        if(cycle)break;
        //memset(visited,0,sizeof(visited));
        if(!visited[i])dfs(i);
    }
    if(!cycle)cout<<-1;
}
int32_t main(){
    IOS;
    int t;
    //cin>>t;
    t=1;
    while(t--)MAIN();
}


#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
#define int long long
#define FI first
#define SE second
#define all(o) o.begin(), o.end()
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0)
#define SZ(x) ((int)(x).size())
#define PB push_back
#define PF push_front
#define MP make_pair
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pii> vii;
typedef long double ld;
typedef long long ll;
int gcd(int x,int y){ return (!y ? x : gcd(y, x%y)); }
int power(int x, int y) { return (!y ? 1 : power(x, y / 2) * power(x, y / 2) * (y % 2 ? x : 1)); }
const int MAXN=5e3+100,MOD=1e9+7;
int mod(int x) { return (x % MOD + MOD) % MOD; }
ll n,k,ans,m;
string s;
vi g[MAXN];
int visited[MAXN],p[MAXN];
void dfs(int d){
    visited[d]=1;
    for(int u:g[d]){
        if(!visited[u]){
            p[u]=d;
            dfs(u);
        }
        else if(u==p[p[d]]){
            cout<<p[p[d]]<<" "<<p[d]<<" "<<d<<" ";
            exit(0);
            return;
        }
    }
    visited[d]=2;
}
void MAIN(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>s;
        s=" "+s;
        for(int j=1;j<=n;j++){
            char ch=s[j];
            if(ch=='1')g[i].PB(j);
        }
    }
    for(int i=1;i<=n;i++){
        if(!visited[i])dfs(i);
    }
    cout<<-1;
}
int32_t main(){
    IOS;
    int t;
    //cin>>t;
    t=1;
    while(t--)MAIN();
}


#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
#define int long long
#define FI first
#define SE second
#define all(o) o.begin(), o.end()
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0)
#define SZ(x) ((int)(x).size())
#define PB push_back
#define PF push_front
#define MP make_pair
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pii> vii;
typedef long double ld;
typedef long long ll;
int gcd(int x,int y){ return (!y ? x : gcd(y, x%y)); }
int power(int x, int y) { return (!y ? 1 : power(x, y / 2) * power(x, y / 2) * (y % 2 ? x : 1)); }
const int MAXN=5e3+100,MOD=1e9+7;
int mod(int x) { return (x % MOD + MOD) % MOD; }
ll n,k,ans,m;
bool cycle;
string s;
vi g[MAXN];
int visited[MAXN],p[MAXN];
void dfs(int d){
    visited[d]=1;
    for(int u:g[d]){
        if(!visited[u]){
            p[u]=d;
            dfs(u);
        }
        else if(u==p[p[d]] && visited[u]==1 && !cycle ){
            cycle=true;
            cout<<p[p[d]]<<" "<<p[d]<<" "<<d<<" ";
            return;
        }
    }
    visited[d]=2;
}
void MAIN(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>s;
        s=" "+s;
        for(int j=1;j<=n;j++){
            char ch=s[j];
            if(ch=='1')g[i].PB(j);
        }
    }
    cycle=false;
    for(int i=1;i<=n;i++){
        if(cycle)break;
        memset(visited,0,sizeof(visited));
        dfs(i);
    }
    if(!cycle)cout<<-1;
}
int32_t main(){
    IOS;
    int t;
    //cin>>t;
    t=1;
    while(t--)MAIN();
}


#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
#define int long long
#define FI first
#define SE second
#define all(o) o.begin(), o.end()
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0)
#define SZ(x) ((int)(x).size())
#define PB push_back
#define PF push_front
#define MP make_pair
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<pii> vii;
typedef long double ld;
typedef long long ll;
int gcd(int x,int y){ return (!y ? x : gcd(y, x%y)); }
int power(int x, int y) { return (!y ? 1 : power(x, y / 2) * power(x, y / 2) * (y % 2 ? x : 1)); }
const int MAXN=5e3+100,MOD=1e9+7;
int mod(int x) { return (x % MOD + MOD) % MOD; }
ll n,k,ans,m;
string s;
string g[MAXN];
int visited[MAXN],p[MAXN];
void dfs(int d,int p){
    visited[d]=1;
    for(int u=1;u<=n;u++){
        if(!visited[u] && g[d][u]=='1')dfs(u,d);
        if(g[d][u]=='1' && g[u][p]=='1'){
            cout<<p<<" "<<d<<" "<<u<<" ";
            exit(0);
        }
    }
}
void MAIN(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>g[i];
        g[i]=" "+g[i];
    }
    for(int i=1;i<=n;i++){
        if(!visited[i])dfs(i,-1);
    }
    cout<<-1;
}
int32_t main(){
    IOS;
    int t;
    //cin>>t;
    t=1;
    while(t--)MAIN();
}


//Ishaan Singh 2019CS10359
#include <iostream>
#include<sstream>
#include<vector>
#include<set>
#include<math.h>
#include<bitset>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long int ll;
typedef long double ld;
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//using namespace __gnu_pbds;
//#define oset tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define fast                          \
    ios_base::sync_with_stdio(false); \
    cin.tie(NULL);                    \
    cout.tie(NULL)
#define fo(i,n) for(int i=0;i<n;i++)
#define PI 3.141592654
#define all(v) (v).begin(), (v).end()
#define allr(v) (v).rbegin(), (v).rend()
#define pb push_back
#define mp make_pair
#define vb vector<bool>
#define vvb vector<vb>
#define vi vector<int>
#define vvi vector<vi>
#define vl vector<ll>
#define vvl vector<vl>
#define pii pair<int, int>
#define vpi vector<pii>
#define unordered_set(T) unordered_set<T, custom_hash>
#define unordered_map(T1, T2) unordered_map<T1, T2, custom_hash>
const ll M=1e9+7;     // large prime for modulo
using namespace std;
/*
ll fpow(ll a,ll b) {// function for binary exponentiation
    a %= M;
    ll res= 1;
    while(b>0) {
        if (b&1){
            res = res * a % M;
        }
        a = a * a % M;
        b >>= 1;
    }
    return res;
}
 ll spf[10000000+1];
ll primes[10000000+1]={false};
 void sieve()  // sieve of eratosthenes
 {
     spf[1] = 1;
     primes[2]=true;
     for (ll i=2; i<10000000+1; i++)
         spf[i] = i;
     for(ll i=4;i<10000000+1;i+=2)
         spf[i]=2;
     for (ll i=3; i*i<10000000+1; i+=2)
     {
         if (spf[i] == i)
         {
             primes[i]=true;
             for (ll j=i*i; j<10000000+1; j+=i)
                 if (spf[j]==j)
                     spf[j] = i;
         }
     }
 }
map<ll,ll> gpf(ll n) // generates prime factors of a number in log(n) time with o(nloglogn) preprocessing time
 {
     map<ll,ll>v;
     ll curr = spf[n];
     ll cnt = 1;
     while (n > 1)
     {
         n/= spf[n];
         if (curr == spf[n])
         {
             cnt++;
             continue;
         }
         v.insert({curr,cnt});
         curr = spf[n];
         cnt = 1;
     }
     return v;
 }
struct comp // comparison function for a pair of integer and pair
{
    bool operator()(const pair<int, pii> &a, const pair<int, pii> &b)
    {
        if (a.first == b.first)
            return a.second.first > b.second.first;
        return a.first < b.first;
    }
};
ll gcd(ll a,ll b){return b ? gcd(b,a%b) :a;}        // returns gcd of two numbers in logarithmic time
map<ll,ll> prsqrt(ll n){                            // returns prime factors of a number in root n time complexity
    ll cnt=0;map<ll,ll>m;
    while (n % 2 == 0){cnt++;n = n/2;}
    if (cnt!=0){m.insert({2,cnt});}
    for (ll i=3;i<=sqrt(n);i+=2){cnt=0;while (n % i == 0){cnt++;n = n/i;}if(cnt!=0){m.insert({i,cnt});}}
    if (n > 2){m.insert({n,1});}
    return m;

}
ll lpfact(ll n,ll p){ll ans=0;while(n){ans+=n/p;n/=p;}return ans;}
//returns largest power of a prime p in n factorial
vector<int>tin(200000+5);vector<int>low(200000+5);
vector<int>adj[2*100000+5];
vpi bridges;
int timer=0;
bool visited[3*100000+5];
void bridge(int v,int p){                   //finding bridges in O(n+m) time
    visited[v]=true;
    tin[v]=low[v]=timer++;
    for(auto u:adj[v]){if (u==p){continue;}else if (visited[u]){low[v]=min(low[v],tin[u]);return;}
        else{bridge(u,v);low[v]=min(low[v],low[u]);if (low[u]>tin[v]){bridges.pb({u,v});}}}}
*/
int fin[100005][12];
int finvicsum(int l,int r,int k){                                       // fenwick tree sum query
    int res=0,resl=0;
    for(int i=r;i>=0;i=(i & (i+1))-1){res+=fin[i][k];}
     for(int i=l-1;i>=0;i=(i & (i+1))-1){resl+=fin[i][k];}
           return res-resl;
}
void finvicupdate(int ind,int val,int k){                               //fenwick tree point update query
       for(int i=ind;i<100005;i=(i|(i+1))){
           fin[i][k]+=val;
       }
}
int used[5004]={0};
int partv=-1;
int parents[5004];
void markcycle(int j,vector<int>adj[]){
    int cv=parents[j];
    while(cv!=j){used[cv]=3;cv=parents[cv];}
}
void findcycle(int u,vector<int>adj[],int p){
    used[u]=2;
    for(int j:adj[u]){
        if (used[j]==0){parents[j]=u;findcycle(j,adj,u);}
        else if (used[j]==2){partv=j;used[j]=3;parents[j]=u;markcycle(j,adj);return;}
        }
    used[u]=1;
}
int main()
{
    fast;
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    int n;cin>>n;vector<int>adj[n+1];int mat[n+1][n+1];fo(i,n){string s;cin>>s;fo(j,n){if (s[j]=='1'){adj[i+1].pb(j+1);mat[i+1][j+1]=1;}else{mat[i+1][j+1]=0;}}}

    fo(i,n){if (!used[i+1]){findcycle(i+1,adj,-1);if (partv!=-1){break;}}}
    if (partv==-1){cout<<-1<<endl;}
    else{
        while(1){
        if (mat[partv][parents[parents[partv]]]){cout<<partv<<" "<<parents[parents[partv]]<<" "<<parents[partv]<<endl;break;}
            else{parents[partv]=parents[parents[partv]];}}
    }

    return 0;
}


//Ishaan Singh 2019CS10359
#include <iostream>
#include<sstream>
#include<vector>
#include<set>
#include<math.h>
#include<bitset>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long int ll;
typedef long double ld;
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//using namespace __gnu_pbds;
//#define oset tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define fast                          \
    ios_base::sync_with_stdio(false); \
    cin.tie(NULL);                    \
    cout.tie(NULL)
#define fo(i,n) for(int i=0;i<n;i++)
#define PI 3.141592654
#define all(v) (v).begin(), (v).end()
#define allr(v) (v).rbegin(), (v).rend()
#define pb push_back
#define mp make_pair
#define vb vector<bool>
#define vvb vector<vb>
#define vi vector<int>
#define vvi vector<vi>
#define vl vector<ll>
#define vvl vector<vl>
#define pii pair<int, int>
#define vpi vector<pii>
#define unordered_set(T) unordered_set<T, custom_hash>
#define unordered_map(T1, T2) unordered_map<T1, T2, custom_hash>
const ll M=1e9+7;     // large prime for modulo
using namespace std;
/*
ll fpow(ll a,ll b) {// function for binary exponentiation
    a %= M;
    ll res= 1;
    while(b>0) {
        if (b&1){
            res = res * a % M;
        }
        a = a * a % M;
        b >>= 1;
    }
    return res;
}
 ll spf[10000000+1];
ll primes[10000000+1]={false};
 void sieve()  // sieve of eratosthenes
 {
     spf[1] = 1;
     primes[2]=true;
     for (ll i=2; i<10000000+1; i++)
         spf[i] = i;
     for(ll i=4;i<10000000+1;i+=2)
         spf[i]=2;
     for (ll i=3; i*i<10000000+1; i+=2)
     {
         if (spf[i] == i)
         {
             primes[i]=true;
             for (ll j=i*i; j<10000000+1; j+=i)
                 if (spf[j]==j)
                     spf[j] = i;
         }
     }
 }
map<ll,ll> gpf(ll n) // generates prime factors of a number in log(n) time with o(nloglogn) preprocessing time
 {
     map<ll,ll>v;
     ll curr = spf[n];
     ll cnt = 1;
     while (n > 1)
     {
         n/= spf[n];
         if (curr == spf[n])
         {
             cnt++;
             continue;
         }
         v.insert({curr,cnt});
         curr = spf[n];
         cnt = 1;
     }
     return v;
 }
struct comp // comparison function for a pair of integer and pair
{
    bool operator()(const pair<int, pii> &a, const pair<int, pii> &b)
    {
        if (a.first == b.first)
            return a.second.first > b.second.first;
        return a.first < b.first;
    }
};
ll gcd(ll a,ll b){return b ? gcd(b,a%b) :a;}        // returns gcd of two numbers in logarithmic time
map<ll,ll> prsqrt(ll n){                            // returns prime factors of a number in root n time complexity
    ll cnt=0;map<ll,ll>m;
    while (n % 2 == 0){cnt++;n = n/2;}
    if (cnt!=0){m.insert({2,cnt});}
    for (ll i=3;i<=sqrt(n);i+=2){cnt=0;while (n % i == 0){cnt++;n = n/i;}if(cnt!=0){m.insert({i,cnt});}}
    if (n > 2){m.insert({n,1});}
    return m;

}
ll lpfact(ll n,ll p){ll ans=0;while(n){ans+=n/p;n/=p;}return ans;}
//returns largest power of a prime p in n factorial
vector<int>tin(200000+5);vector<int>low(200000+5);
vector<int>adj[2*100000+5];
vpi bridges;
int timer=0;
bool visited[3*100000+5];
void bridge(int v,int p){                   //finding bridges in O(n+m) time
    visited[v]=true;
    tin[v]=low[v]=timer++;
    for(auto u:adj[v]){if (u==p){continue;}else if (visited[u]){low[v]=min(low[v],tin[u]);return;}
        else{bridge(u,v);low[v]=min(low[v],low[u]);if (low[u]>tin[v]){bridges.pb({u,v});}}}}
*/
int fin[100005][12];
int finvicsum(int l,int r,int k){                                       // fenwick tree sum query
    int res=0,resl=0;
    for(int i=r;i>=0;i=(i & (i+1))-1){res+=fin[i][k];}
     for(int i=l-1;i>=0;i=(i & (i+1))-1){resl+=fin[i][k];}
           return res-resl;
}
void finvicupdate(int ind,int val,int k){                               //fenwick tree point update query
       for(int i=ind;i<100005;i=(i|(i+1))){
           fin[i][k]+=val;
       }
}
/*
int used[5004]={0};
int partv=-1;
int parents[5004];
void markcycle(int j,vector<int>adj[]){
    for(int h:adj[j]){if (used[h]==2){used[h]=3;parents[h]=j;markcycle(h,adj);}}
}
void findcycle(int u,vector<int>adj[],int p){
    used[u]=2;
    for(int j:adj[u]){
        if (used[j]==0){parents[j]=u;findcycle(j,adj,u);}
        else if (used[j]==2){partv=j;used[j]=3;parents[j]=u;return;}
        }
    used[u]=1;
}
 */
int main()
{
    fast;
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    int n;cin>>n;vector<int>adj[n+1];int outdegree[n+1];fo(i,n){outdegree[i+1]=0;}int mat[n+1][n+1];fo(i,n){string s;cin>>s;fo(j,n){if (s[j]=='1'){mat[i+1][j+1]=1;outdegree[i+1]++;}else{mat[i+1][j+1]=0;}}}
    int bc=0;
    fo(i,n){if (bc==1){break;}fo(j,n){if (mat[i+1][j+1]==1 && outdegree[j+1]>=outdegree[i+1]){bc=1;
        cout<<i+1<<" "<<j+1<<" ";
        fo(k,n){if (mat[j+1][k+1]==1 && mat[k+1][i+1]==1){cout<<k+1<<endl;break;}
        }}break;}}
    if (bc==0){cout<<-1<<endl;}
    return 0;
}


//Ishaan Singh 2019CS10359
#include <iostream>
#include<sstream>
#include<vector>
#include<set>
#include<math.h>
#include<bitset>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long int ll;
typedef long double ld;
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//using namespace __gnu_pbds;
//#define oset tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define fast                          \
    ios_base::sync_with_stdio(false); \
    cin.tie(NULL);                    \
    cout.tie(NULL)
#define fo(i,n) for(int i=0;i<n;i++)
#define PI 3.141592654
#define all(v) (v).begin(), (v).end()
#define allr(v) (v).rbegin(), (v).rend()
#define pb push_back
#define mp make_pair
#define vb vector<bool>
#define vvb vector<vb>
#define vi vector<int>
#define vvi vector<vi>
#define vl vector<ll>
#define vvl vector<vl>
#define pii pair<int, int>
#define vpi vector<pii>
#define unordered_set(T) unordered_set<T, custom_hash>
#define unordered_map(T1, T2) unordered_map<T1, T2, custom_hash>
const ll M=1e9+7;     // large prime for modulo
using namespace std;
/*
ll fpow(ll a,ll b) {// function for binary exponentiation
    a %= M;
    ll res= 1;
    while(b>0) {
        if (b&1){
            res = res * a % M;
        }
        a = a * a % M;
        b >>= 1;
    }
    return res;
}
 ll spf[10000000+1];
ll primes[10000000+1]={false};
 void sieve()  // sieve of eratosthenes
 {
     spf[1] = 1;
     primes[2]=true;
     for (ll i=2; i<10000000+1; i++)
         spf[i] = i;
     for(ll i=4;i<10000000+1;i+=2)
         spf[i]=2;
     for (ll i=3; i*i<10000000+1; i+=2)
     {
         if (spf[i] == i)
         {
             primes[i]=true;
             for (ll j=i*i; j<10000000+1; j+=i)
                 if (spf[j]==j)
                     spf[j] = i;
         }
     }
 }
map<ll,ll> gpf(ll n) // generates prime factors of a number in log(n) time with o(nloglogn) preprocessing time
 {
     map<ll,ll>v;
     ll curr = spf[n];
     ll cnt = 1;
     while (n > 1)
     {
         n/= spf[n];
         if (curr == spf[n])
         {
             cnt++;
             continue;
         }
         v.insert({curr,cnt});
         curr = spf[n];
         cnt = 1;
     }
     return v;
 }
struct comp // comparison function for a pair of integer and pair
{
    bool operator()(const pair<int, pii> &a, const pair<int, pii> &b)
    {
        if (a.first == b.first)
            return a.second.first > b.second.first;
        return a.first < b.first;
    }
};
ll gcd(ll a,ll b){return b ? gcd(b,a%b) :a;}        // returns gcd of two numbers in logarithmic time
map<ll,ll> prsqrt(ll n){                            // returns prime factors of a number in root n time complexity
    ll cnt=0;map<ll,ll>m;
    while (n % 2 == 0){cnt++;n = n/2;}
    if (cnt!=0){m.insert({2,cnt});}
    for (ll i=3;i<=sqrt(n);i+=2){cnt=0;while (n % i == 0){cnt++;n = n/i;}if(cnt!=0){m.insert({i,cnt});}}
    if (n > 2){m.insert({n,1});}
    return m;

}
ll lpfact(ll n,ll p){ll ans=0;while(n){ans+=n/p;n/=p;}return ans;}
//returns largest power of a prime p in n factorial
vector<int>tin(200000+5);vector<int>low(200000+5);
vector<int>adj[2*100000+5];
vpi bridges;
int timer=0;
bool visited[3*100000+5];
void bridge(int v,int p){                   //finding bridges in O(n+m) time
    visited[v]=true;
    tin[v]=low[v]=timer++;
    for(auto u:adj[v]){if (u==p){continue;}else if (visited[u]){low[v]=min(low[v],tin[u]);return;}
        else{bridge(u,v);low[v]=min(low[v],low[u]);if (low[u]>tin[v]){bridges.pb({u,v});}}}}
*/
int fin[100005][12];
int finvicsum(int l,int r,int k){                                       // fenwick tree sum query
    int res=0,resl=0;
    for(int i=r;i>=0;i=(i & (i+1))-1){res+=fin[i][k];}
     for(int i=l-1;i>=0;i=(i & (i+1))-1){resl+=fin[i][k];}
           return res-resl;
}
void finvicupdate(int ind,int val,int k){                               //fenwick tree point update query
       for(int i=ind;i<100005;i=(i|(i+1))){
           fin[i][k]+=val;
       }
}
int used[5004]={0};
int partv=-1;
int parents[5004];
/*
void markcycle(int j,vector<int>adj[]){
    for(int h:adj[j]){if (used[h]==2){used[h]=3;parents[h]=j;markcycle(h,adj);}}
}
*/
void findcycle(int u,vector<int>adj[],int p){
    used[u]=2;
    for(int j:adj[u]){
        if (used[j]==0){parents[j]=u;findcycle(j,adj,u);}
        else if (used[j]==2){partv=j;used[j]=3;parents[j]=u;return;}
        }
    used[u]=1;
}
int main()
{
    fast;
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    int n;cin>>n;vector<int>adj[n+1];int mat[n+1][n+1];fo(i,n){string s;cin>>s;fo(j,n){if (s[j]=='1'){adj[i+1].pb(j+1);mat[i+1][j+1]=1;}else{mat[i+1][j+1]=0;}}}
    fo(i,n){if (!used[i+1]){findcycle(i+1,adj,-1);if (partv!=-1){break;}}}
    if (partv==-1){cout<<-1<<endl;}
    else{
        while(true){
            if(mat[partv][parents[parents[partv]]]==1)
        {cout<<partv<<" "<<parents[parents[partv]]<<" "<<parents[partv]<<endl;break;}
            else{parents[partv]=parents[parents[partv]];}

        }
    }
    return 0;
}


//Ishaan Singh 2019CS10359
#include <iostream>
#include<sstream>
#include<vector>
#include<set>
#include<math.h>
#include<bitset>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long int ll;
typedef long double ld;
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//using namespace __gnu_pbds;
//#define oset tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define fast                          \
    ios_base::sync_with_stdio(false); \
    cin.tie(NULL);                    \
    cout.tie(NULL)
#define fo(i,n) for(int i=0;i<n;i++)
#define PI 3.141592654
#define all(v) (v).begin(), (v).end()
#define allr(v) (v).rbegin(), (v).rend()
#define pb push_back
#define mp make_pair
#define vb vector<bool>
#define vvb vector<vb>
#define vi vector<int>
#define vvi vector<vi>
#define vl vector<ll>
#define vvl vector<vl>
#define pii pair<int, int>
#define vpi vector<pii>
#define unordered_set(T) unordered_set<T, custom_hash>
#define unordered_map(T1, T2) unordered_map<T1, T2, custom_hash>
const ll M=1e9+7;     // large prime for modulo
using namespace std;
/*
ll fpow(ll a,ll b) {// function for binary exponentiation
    a %= M;
    ll res= 1;
    while(b>0) {
        if (b&1){
            res = res * a % M;
        }
        a = a * a % M;
        b >>= 1;
    }
    return res;
}
 ll spf[10000000+1];
ll primes[10000000+1]={false};
 void sieve()  // sieve of eratosthenes
 {
     spf[1] = 1;
     primes[2]=true;
     for (ll i=2; i<10000000+1; i++)
         spf[i] = i;
     for(ll i=4;i<10000000+1;i+=2)
         spf[i]=2;
     for (ll i=3; i*i<10000000+1; i+=2)
     {
         if (spf[i] == i)
         {
             primes[i]=true;
             for (ll j=i*i; j<10000000+1; j+=i)
                 if (spf[j]==j)
                     spf[j] = i;
         }
     }
 }
map<ll,ll> gpf(ll n) // generates prime factors of a number in log(n) time with o(nloglogn) preprocessing time
 {
     map<ll,ll>v;
     ll curr = spf[n];
     ll cnt = 1;
     while (n > 1)
     {
         n/= spf[n];
         if (curr == spf[n])
         {
             cnt++;
             continue;
         }
         v.insert({curr,cnt});
         curr = spf[n];
         cnt = 1;
     }
     return v;
 }
struct comp // comparison function for a pair of integer and pair
{
    bool operator()(const pair<int, pii> &a, const pair<int, pii> &b)
    {
        if (a.first == b.first)
            return a.second.first > b.second.first;
        return a.first < b.first;
    }
};
ll gcd(ll a,ll b){return b ? gcd(b,a%b) :a;}        // returns gcd of two numbers in logarithmic time
map<ll,ll> prsqrt(ll n){                            // returns prime factors of a number in root n time complexity
    ll cnt=0;map<ll,ll>m;
    while (n % 2 == 0){cnt++;n = n/2;}
    if (cnt!=0){m.insert({2,cnt});}
    for (ll i=3;i<=sqrt(n);i+=2){cnt=0;while (n % i == 0){cnt++;n = n/i;}if(cnt!=0){m.insert({i,cnt});}}
    if (n > 2){m.insert({n,1});}
    return m;

}
ll lpfact(ll n,ll p){ll ans=0;while(n){ans+=n/p;n/=p;}return ans;}
//returns largest power of a prime p in n factorial
vector<int>tin(200000+5);vector<int>low(200000+5);
vector<int>adj[2*100000+5];
vpi bridges;
int timer=0;
bool visited[3*100000+5];
void bridge(int v,int p){                   //finding bridges in O(n+m) time
    visited[v]=true;
    tin[v]=low[v]=timer++;
    for(auto u:adj[v]){if (u==p){continue;}else if (visited[u]){low[v]=min(low[v],tin[u]);return;}
        else{bridge(u,v);low[v]=min(low[v],low[u]);if (low[u]>tin[v]){bridges.pb({u,v});}}}}
*/
int fin[100005][12];
int finvicsum(int l,int r,int k){                                       // fenwick tree sum query
    int res=0,resl=0;
    for(int i=r;i>=0;i=(i & (i+1))-1){res+=fin[i][k];}
     for(int i=l-1;i>=0;i=(i & (i+1))-1){resl+=fin[i][k];}
           return res-resl;
}
void finvicupdate(int ind,int val,int k){                               //fenwick tree point update query
       for(int i=ind;i<100005;i=(i|(i+1))){
           fin[i][k]+=val;
       }
}
/*
int used[5004]={0};
int partv=-1;
int parents[5004];
void markcycle(int j,vector<int>adj[]){
    for(int h:adj[j]){if (used[h]==2){used[h]=3;parents[h]=j;markcycle(h,adj);}}
}
void findcycle(int u,vector<int>adj[],int p){
    used[u]=2;
    for(int j:adj[u]){
        if (used[j]==0){parents[j]=u;findcycle(j,adj,u);}
        else if (used[j]==2){partv=j;used[j]=3;parents[j]=u;return;}
        }
    used[u]=1;
}
 */
int main()
{
    fast;
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    int n;cin>>n;vector<int>adj[n+1];int outdegree[n+1];fo(i,n){outdegree[i+1]=0;}int mat[n+1][n+1];fo(i,n){string s;cin>>s;fo(j,n){if (s[j]=='1'){mat[i+1][j+1]=1;outdegree[i+1]++;}else{mat[i+1][j+1]=0;}}}
    int bc=0;
    fo(i,n){if (bc==1){break;}fo(j,n){if (mat[i+1][j+1]==1 && outdegree[j+1]>=outdegree[i+1]){bc=1;
        cout<<i+1<<" "<<j+1<<" ";
        fo(k,n){if (mat[j+1][k+1]==1 && mat[k+1][i+1]==1){cout<<k+1<<endl;break;}
        }}}}
    if (bc==0){cout<<-1<<endl;}
    return 0;
}


//Ishaan Singh 2019CS10359
#include <iostream>
#include<sstream>
#include<vector>
#include<set>
#include<math.h>
#include<bitset>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long int ll;
typedef long double ld;
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//using namespace __gnu_pbds;
//#define oset tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define fast                          \
    ios_base::sync_with_stdio(false); \
    cin.tie(NULL);                    \
    cout.tie(NULL)
#define fo(i,n) for(int i=0;i<n;i++)
#define PI 3.141592654
#define all(v) (v).begin(), (v).end()
#define allr(v) (v).rbegin(), (v).rend()
#define pb push_back
#define mp make_pair
#define vb vector<bool>
#define vvb vector<vb>
#define vi vector<int>
#define vvi vector<vi>
#define vl vector<ll>
#define vvl vector<vl>
#define pii pair<int, int>
#define vpi vector<pii>
#define unordered_set(T) unordered_set<T, custom_hash>
#define unordered_map(T1, T2) unordered_map<T1, T2, custom_hash>
const ll M=1e9+7;     // large prime for modulo
using namespace std;
/*
ll fpow(ll a,ll b) {// function for binary exponentiation
    a %= M;
    ll res= 1;
    while(b>0) {
        if (b&1){
            res = res * a % M;
        }
        a = a * a % M;
        b >>= 1;
    }
    return res;
}
 ll spf[10000000+1];
ll primes[10000000+1]={false};
 void sieve()  // sieve of eratosthenes
 {
     spf[1] = 1;
     primes[2]=true;
     for (ll i=2; i<10000000+1; i++)
         spf[i] = i;
     for(ll i=4;i<10000000+1;i+=2)
         spf[i]=2;
     for (ll i=3; i*i<10000000+1; i+=2)
     {
         if (spf[i] == i)
         {
             primes[i]=true;
             for (ll j=i*i; j<10000000+1; j+=i)
                 if (spf[j]==j)
                     spf[j] = i;
         }
     }
 }
map<ll,ll> gpf(ll n) // generates prime factors of a number in log(n) time with o(nloglogn) preprocessing time
 {
     map<ll,ll>v;
     ll curr = spf[n];
     ll cnt = 1;
     while (n > 1)
     {
         n/= spf[n];
         if (curr == spf[n])
         {
             cnt++;
             continue;
         }
         v.insert({curr,cnt});
         curr = spf[n];
         cnt = 1;
     }
     return v;
 }
struct comp // comparison function for a pair of integer and pair
{
    bool operator()(const pair<int, pii> &a, const pair<int, pii> &b)
    {
        if (a.first == b.first)
            return a.second.first > b.second.first;
        return a.first < b.first;
    }
};
ll gcd(ll a,ll b){return b ? gcd(b,a%b) :a;}        // returns gcd of two numbers in logarithmic time
map<ll,ll> prsqrt(ll n){                            // returns prime factors of a number in root n time complexity
    ll cnt=0;map<ll,ll>m;
    while (n % 2 == 0){cnt++;n = n/2;}
    if (cnt!=0){m.insert({2,cnt});}
    for (ll i=3;i<=sqrt(n);i+=2){cnt=0;while (n % i == 0){cnt++;n = n/i;}if(cnt!=0){m.insert({i,cnt});}}
    if (n > 2){m.insert({n,1});}
    return m;

}
ll lpfact(ll n,ll p){ll ans=0;while(n){ans+=n/p;n/=p;}return ans;}
//returns largest power of a prime p in n factorial
vector<int>tin(200000+5);vector<int>low(200000+5);
vector<int>adj[2*100000+5];
vpi bridges;
int timer=0;
bool visited[3*100000+5];
void bridge(int v,int p){                   //finding bridges in O(n+m) time
    visited[v]=true;
    tin[v]=low[v]=timer++;
    for(auto u:adj[v]){if (u==p){continue;}else if (visited[u]){low[v]=min(low[v],tin[u]);return;}
        else{bridge(u,v);low[v]=min(low[v],low[u]);if (low[u]>tin[v]){bridges.pb({u,v});}}}}
*/
int fin[100005][12];
int finvicsum(int l,int r,int k){                                       // fenwick tree sum query
    int res=0,resl=0;
    for(int i=r;i>=0;i=(i & (i+1))-1){res+=fin[i][k];}
     for(int i=l-1;i>=0;i=(i & (i+1))-1){resl+=fin[i][k];}
           return res-resl;
}
void finvicupdate(int ind,int val,int k){                               //fenwick tree point update query
       for(int i=ind;i<100005;i=(i|(i+1))){
           fin[i][k]+=val;
       }
}
int used[5004]={0};
int partv=-1;
int parents[5004];
void markcycle(int j,vector<int>adj[]){
    for(int h:adj[j]){if (used[h]==2){used[h]=3;parents[h]=j;markcycle(h,adj);}}
}
void findcycle(int u,vector<int>adj[],int p){
    used[u]=2;
    for(int j:adj[u]){
        if (used[j]==0){parents[j]=u;findcycle(j,adj,u);}
        else if (used[j]==2){partv=j;used[j]=3;parents[j]=u;markcycle(j,adj);return;}
        }
    used[u]=1;
}
int main()
{
    fast;
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    int n;cin>>n;vector<int>adj[n+1];int mat[n+1][n+1];fo(i,n){string s;cin>>s;fo(j,n){if (s[j]=='1'){adj[i+1].pb(j+1);mat[i+1][j+1]=1;}else{mat[i+1][j+1]=0;}}}
    fo(i,n){if (!used[i+1]){findcycle(i+1,adj,-1);if (partv!=-1){break;}}}
    if (partv==-1){cout<<-1<<endl;}
    else{
        while(1){
        if (mat[partv][parents[parents[partv]]]){cout<<partv<<" "<<parents[parents[partv]]<<" "<<parents[partv]<<endl;break;}
            else{parents[partv]=parents[parents[partv]];}}
    }
    return 0;
}


//Ishaan Singh 2019CS10359
#include <iostream>
#include<sstream>
#include<vector>
#include<set>
#include<math.h>
#include<bitset>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long int ll;
typedef long double ld;
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//using namespace __gnu_pbds;
//#define oset tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define fast                          \
    ios_base::sync_with_stdio(false); \
    cin.tie(NULL);                    \
    cout.tie(NULL)
#define fo(i,n) for(int i=0;i<n;i++)
#define PI 3.141592654
#define all(v) (v).begin(), (v).end()
#define allr(v) (v).rbegin(), (v).rend()
#define pb push_back
#define mp make_pair
#define vb vector<bool>
#define vvb vector<vb>
#define vi vector<int>
#define vvi vector<vi>
#define vl vector<ll>
#define vvl vector<vl>
#define pii pair<int, int>
#define vpi vector<pii>
#define unordered_set(T) unordered_set<T, custom_hash>
#define unordered_map(T1, T2) unordered_map<T1, T2, custom_hash>
const ll M=1e9+7;     // large prime for modulo
using namespace std;
/*
ll fpow(ll a,ll b) {// function for binary exponentiation
    a %= M;
    ll res= 1;
    while(b>0) {
        if (b&1){
            res = res * a % M;
        }
        a = a * a % M;
        b >>= 1;
    }
    return res;
}
 ll spf[10000000+1];
ll primes[10000000+1]={false};
 void sieve()  // sieve of eratosthenes
 {
     spf[1] = 1;
     primes[2]=true;
     for (ll i=2; i<10000000+1; i++)
         spf[i] = i;
     for(ll i=4;i<10000000+1;i+=2)
         spf[i]=2;
     for (ll i=3; i*i<10000000+1; i+=2)
     {
         if (spf[i] == i)
         {
             primes[i]=true;
             for (ll j=i*i; j<10000000+1; j+=i)
                 if (spf[j]==j)
                     spf[j] = i;
         }
     }
 }
map<ll,ll> gpf(ll n) // generates prime factors of a number in log(n) time with o(nloglogn) preprocessing time
 {
     map<ll,ll>v;
     ll curr = spf[n];
     ll cnt = 1;
     while (n > 1)
     {
         n/= spf[n];
         if (curr == spf[n])
         {
             cnt++;
             continue;
         }
         v.insert({curr,cnt});
         curr = spf[n];
         cnt = 1;
     }
     return v;
 }
struct comp // comparison function for a pair of integer and pair
{
    bool operator()(const pair<int, pii> &a, const pair<int, pii> &b)
    {
        if (a.first == b.first)
            return a.second.first > b.second.first;
        return a.first < b.first;
    }
};
ll gcd(ll a,ll b){return b ? gcd(b,a%b) :a;}        // returns gcd of two numbers in logarithmic time
map<ll,ll> prsqrt(ll n){                            // returns prime factors of a number in root n time complexity
    ll cnt=0;map<ll,ll>m;
    while (n % 2 == 0){cnt++;n = n/2;}
    if (cnt!=0){m.insert({2,cnt});}
    for (ll i=3;i<=sqrt(n);i+=2){cnt=0;while (n % i == 0){cnt++;n = n/i;}if(cnt!=0){m.insert({i,cnt});}}
    if (n > 2){m.insert({n,1});}
    return m;

}
ll lpfact(ll n,ll p){ll ans=0;while(n){ans+=n/p;n/=p;}return ans;}
//returns largest power of a prime p in n factorial
vector<int>tin(200000+5);vector<int>low(200000+5);
vector<int>adj[2*100000+5];
vpi bridges;
int timer=0;
bool visited[3*100000+5];
void bridge(int v,int p){                   //finding bridges in O(n+m) time
    visited[v]=true;
    tin[v]=low[v]=timer++;
    for(auto u:adj[v]){if (u==p){continue;}else if (visited[u]){low[v]=min(low[v],tin[u]);return;}
        else{bridge(u,v);low[v]=min(low[v],low[u]);if (low[u]>tin[v]){bridges.pb({u,v});}}}}
*/
int fin[100005][12];
int finvicsum(int l,int r,int k){                                       // fenwick tree sum query
    int res=0,resl=0;
    for(int i=r;i>=0;i=(i & (i+1))-1){res+=fin[i][k];}
     for(int i=l-1;i>=0;i=(i & (i+1))-1){resl+=fin[i][k];}
           return res-resl;
}
void finvicupdate(int ind,int val,int k){                               //fenwick tree point update query
       for(int i=ind;i<100005;i=(i|(i+1))){
           fin[i][k]+=val;
       }
}
int used[5004]={0};
int partv=-1;
int parents[5004];
void markcycle(int j,vector<int>adj[]){
    for(int h:adj[j]){if (used[h]==2){used[h]=3;parents[h]=j;markcycle(h,adj);}}
}
void findcycle(int u,vector<int>adj[],int p){
    used[u]=2;
    for(int j:adj[u]){
        if (used[j]==0){findcycle(j,adj,u);}
        else if (used[j]==2){partv=j;used[j]=3;parents[j]=u;markcycle(j,adj);return;}
        }
    used[u]=1;
}
int main()
{
    fast;
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    int n;cin>>n;vector<int>adj[n+1];int mat[n+1][n+1];fo(i,n){string s;cin>>s;fo(j,n){if (s[j]=='1'){adj[i+1].pb(j+1);mat[i+1][j+1]=1;}else{mat[i+1][j+1]=0;}}}
    fo(i,n){if (!used[i+1]){findcycle(i+1,adj,-1);if (partv!=-1){break;}}}
    if (partv==-1){cout<<-1<<endl;}
    else{
        while(1){
        if (mat[partv][parents[parents[partv]]]){cout<<partv<<" "<<parents[parents[partv]]<<" "<<parents[partv]<<endl;break;}
            else{parents[partv]=parents[parents[partv]];}

        }
    }
    return 0;
}


//Ishaan Singh 2019CS10359
#include <iostream>
#include<sstream>
#include<vector>
#include<set>
#include<math.h>
#include<bitset>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long int ll;
typedef long double ld;
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//using namespace __gnu_pbds;
//#define oset tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define fast                          \
    ios_base::sync_with_stdio(false); \
    cin.tie(NULL);                    \
    cout.tie(NULL)
#define fo(i,n) for(int i=0;i<n;i++)
#define PI 3.141592654
#define all(v) (v).begin(), (v).end()
#define allr(v) (v).rbegin(), (v).rend()
#define pb push_back
#define mp make_pair
#define vb vector<bool>
#define vvb vector<vb>
#define vi vector<int>
#define vvi vector<vi>
#define vl vector<ll>
#define vvl vector<vl>
#define pii pair<int, int>
#define vpi vector<pii>
#define unordered_set(T) unordered_set<T, custom_hash>
#define unordered_map(T1, T2) unordered_map<T1, T2, custom_hash>
const ll M=1e9+7;     // large prime for modulo
using namespace std;
/*
ll fpow(ll a,ll b) {// function for binary exponentiation
    a %= M;
    ll res= 1;
    while(b>0) {
        if (b&1){
            res = res * a % M;
        }
        a = a * a % M;
        b >>= 1;
    }
    return res;
}
 ll spf[10000000+1];
ll primes[10000000+1]={false};
 void sieve()  // sieve of eratosthenes
 {
     spf[1] = 1;
     primes[2]=true;
     for (ll i=2; i<10000000+1; i++)
         spf[i] = i;
     for(ll i=4;i<10000000+1;i+=2)
         spf[i]=2;
     for (ll i=3; i*i<10000000+1; i+=2)
     {
         if (spf[i] == i)
         {
             primes[i]=true;
             for (ll j=i*i; j<10000000+1; j+=i)
                 if (spf[j]==j)
                     spf[j] = i;
         }
     }
 }
map<ll,ll> gpf(ll n) // generates prime factors of a number in log(n) time with o(nloglogn) preprocessing time
 {
     map<ll,ll>v;
     ll curr = spf[n];
     ll cnt = 1;
     while (n > 1)
     {
         n/= spf[n];
         if (curr == spf[n])
         {
             cnt++;
             continue;
         }
         v.insert({curr,cnt});
         curr = spf[n];
         cnt = 1;
     }
     return v;
 }
struct comp // comparison function for a pair of integer and pair
{
    bool operator()(const pair<int, pii> &a, const pair<int, pii> &b)
    {
        if (a.first == b.first)
            return a.second.first > b.second.first;
        return a.first < b.first;
    }
};
ll gcd(ll a,ll b){return b ? gcd(b,a%b) :a;}        // returns gcd of two numbers in logarithmic time
map<ll,ll> prsqrt(ll n){                            // returns prime factors of a number in root n time complexity
    ll cnt=0;map<ll,ll>m;
    while (n % 2 == 0){cnt++;n = n/2;}
    if (cnt!=0){m.insert({2,cnt});}
    for (ll i=3;i<=sqrt(n);i+=2){cnt=0;while (n % i == 0){cnt++;n = n/i;}if(cnt!=0){m.insert({i,cnt});}}
    if (n > 2){m.insert({n,1});}
    return m;

}
ll lpfact(ll n,ll p){ll ans=0;while(n){ans+=n/p;n/=p;}return ans;}
//returns largest power of a prime p in n factorial
vector<int>tin(200000+5);vector<int>low(200000+5);
vector<int>adj[2*100000+5];
vpi bridges;
int timer=0;
bool visited[3*100000+5];
void bridge(int v,int p){                   //finding bridges in O(n+m) time
    visited[v]=true;
    tin[v]=low[v]=timer++;
    for(auto u:adj[v]){if (u==p){continue;}else if (visited[u]){low[v]=min(low[v],tin[u]);return;}
        else{bridge(u,v);low[v]=min(low[v],low[u]);if (low[u]>tin[v]){bridges.pb({u,v});}}}}
*/
int fin[100005][12];
int finvicsum(int l,int r,int k){                                       // fenwick tree sum query
    int res=0,resl=0;
    for(int i=r;i>=0;i=(i & (i+1))-1){res+=fin[i][k];}
     for(int i=l-1;i>=0;i=(i & (i+1))-1){resl+=fin[i][k];}
           return res-resl;
}
void finvicupdate(int ind,int val,int k){                               //fenwick tree point update query
       for(int i=ind;i<100005;i=(i|(i+1))){
           fin[i][k]+=val;
       }
}
/*
int used[5004]={0};
int partv=-1;
int parents[5004];
void markcycle(int j,vector<int>adj[]){
    for(int h:adj[j]){if (used[h]==2){used[h]=3;parents[h]=j;markcycle(h,adj);}}
}
void findcycle(int u,vector<int>adj[],int p){
    used[u]=2;
    for(int j:adj[u]){
        if (used[j]==0){parents[j]=u;findcycle(j,adj,u);}
        else if (used[j]==2){partv=j;used[j]=3;parents[j]=u;return;}
        }
    used[u]=1;
}
 */
int main()
{
    fast;
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    int n;cin>>n;vector<int>adj[n+1];int outdegree[n+1];fo(i,n){outdegree[i+1]=0;}int mat[n+1][n+1];fo(i,n){string s;cin>>s;fo(j,n){if (s[j]=='1'){mat[i+1][j+1]=1;outdegree[i+1]++;}else{mat[i+1][j+1]=0;}}}
    int bc=0;
    fo(i,n){if (bc==1){break;}fo(j,n){if (mat[i+1][j+1]==1 && outdegree[j+1]>=outdegree[i+1]){bc=1;
        cout<<i+1<<" "<<j+1<<" ";
        fo(k,n){if (mat[j+1][k+1]==1 && mat[k+1][i+1]==1){cout<<k+1<<endl;break;}
        }break;}}}
    if (bc==0){cout<<-1<<endl;}
    return 0;
}


//Ishaan Singh 2019CS10359
#include <iostream>
#include<sstream>
#include<vector>
#include<set>
#include<math.h>
#include<bitset>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long int ll;
typedef long double ld;
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//using namespace __gnu_pbds;
//#define oset tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
#define fast                          \
    ios_base::sync_with_stdio(false); \
    cin.tie(NULL);                    \
    cout.tie(NULL)
#define fo(i,n) for(int i=0;i<n;i++)
#define PI 3.141592654
#define all(v) (v).begin(), (v).end()
#define allr(v) (v).rbegin(), (v).rend()
#define pb push_back
#define mp make_pair
#define vb vector<bool>
#define vvb vector<vb>
#define vi vector<int>
#define vvi vector<vi>
#define vl vector<ll>
#define vvl vector<vl>
#define pii pair<int, int>
#define vpi vector<pii>
#define unordered_set(T) unordered_set<T, custom_hash>
#define unordered_map(T1, T2) unordered_map<T1, T2, custom_hash>
const ll M=1e9+7;     // large prime for modulo
using namespace std;
/*
ll fpow(ll a,ll b) {// function for binary exponentiation
    a %= M;
    ll res= 1;
    while(b>0) {
        if (b&1){
            res = res * a % M;
        }
        a = a * a % M;
        b >>= 1;
    }
    return res;
}
 ll spf[10000000+1];
ll primes[10000000+1]={false};
 void sieve()  // sieve of eratosthenes
 {
     spf[1] = 1;
     primes[2]=true;
     for (ll i=2; i<10000000+1; i++)
         spf[i] = i;
     for(ll i=4;i<10000000+1;i+=2)
         spf[i]=2;
     for (ll i=3; i*i<10000000+1; i+=2)
     {
         if (spf[i] == i)
         {
             primes[i]=true;
             for (ll j=i*i; j<10000000+1; j+=i)
                 if (spf[j]==j)
                     spf[j] = i;
         }
     }
 }
map<ll,ll> gpf(ll n) // generates prime factors of a number in log(n) time with o(nloglogn) preprocessing time
 {
     map<ll,ll>v;
     ll curr = spf[n];
     ll cnt = 1;
     while (n > 1)
     {
         n/= spf[n];
         if (curr == spf[n])
         {
             cnt++;
             continue;
         }
         v.insert({curr,cnt});
         curr = spf[n];
         cnt = 1;
     }
     return v;
 }
struct comp // comparison function for a pair of integer and pair
{
    bool operator()(const pair<int, pii> &a, const pair<int, pii> &b)
    {
        if (a.first == b.first)
            return a.second.first > b.second.first;
        return a.first < b.first;
    }
};
ll gcd(ll a,ll b){return b ? gcd(b,a%b) :a;}        // returns gcd of two numbers in logarithmic time
map<ll,ll> prsqrt(ll n){                            // returns prime factors of a number in root n time complexity
    ll cnt=0;map<ll,ll>m;
    while (n % 2 == 0){cnt++;n = n/2;}
    if (cnt!=0){m.insert({2,cnt});}
    for (ll i=3;i<=sqrt(n);i+=2){cnt=0;while (n % i == 0){cnt++;n = n/i;}if(cnt!=0){m.insert({i,cnt});}}
    if (n > 2){m.insert({n,1});}
    return m;

}
ll lpfact(ll n,ll p){ll ans=0;while(n){ans+=n/p;n/=p;}return ans;}
//returns largest power of a prime p in n factorial
vector<int>tin(200000+5);vector<int>low(200000+5);
vector<int>adj[2*100000+5];
vpi bridges;
int timer=0;
bool visited[3*100000+5];
void bridge(int v,int p){                   //finding bridges in O(n+m) time
    visited[v]=true;
    tin[v]=low[v]=timer++;
    for(auto u:adj[v]){if (u==p){continue;}else if (visited[u]){low[v]=min(low[v],tin[u]);return;}
        else{bridge(u,v);low[v]=min(low[v],low[u]);if (low[u]>tin[v]){bridges.pb({u,v});}}}}
*/
int fin[100005][12];
int finvicsum(int l,int r,int k){                                       // fenwick tree sum query
    int res=0,resl=0;
    for(int i=r;i>=0;i=(i & (i+1))-1){res+=fin[i][k];}
     for(int i=l-1;i>=0;i=(i & (i+1))-1){resl+=fin[i][k];}
           return res-resl;
}
void finvicupdate(int ind,int val,int k){                               //fenwick tree point update query
       for(int i=ind;i<100005;i=(i|(i+1))){
           fin[i][k]+=val;
       }
}
int used[5004]={0};
int partv=-1;
int parents[5004];
/*
void markcycle(int j,vector<int>adj[]){
    for(int h:adj[j]){if (used[h]==2){used[h]=3;parents[h]=j;markcycle(h,adj);}}
}
*/
void findcycle(int u,vector<int>adj[],int p){
    used[u]=2;
    for(int j:adj[u]){
        if (used[j]==0){parents[j]=u;findcycle(j,adj,u);}
        else if (used[j]==2){partv=j;used[j]=3;parents[j]=u;return;}
        }
    used[u]=1;
}
int main()
{
    fast;
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    int n;cin>>n;vector<int>adj[n+1];int mat[n+1][n+1];fo(i,n){string s;cin>>s;fo(j,n){if (s[j]=='1'){adj[i+1].pb(j+1);mat[i+1][j+1]=1;}else{mat[i+1][j+1]=0;}}}
    fo(i,n){if (used[i+1]==0){findcycle(i+1,adj,-1);if (partv!=-1){break;}}}
    if (partv==-1){cout<<-1<<endl;}
    else{
        while(true){
            if(mat[partv][parents[parents[partv]]]==1)
        {cout<<partv<<" "<<parents[parents[partv]]<<" "<<parents[partv]<<endl;break;}
            else{parents[partv]=parents[parents[partv]];}

        }
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define int long long
int mod=1e9+7;
int min(int a,int b){
  return (a<b)?a:b;
}
int max(int a,int b){
  return (a>b)?a:b;
}
int fp(int a,int b){
  if(b==0) return 1;
  int x=fp(a,b/2);
  x=(x*x)%mod;
  if(b&1) x=(x*a)%mod;
  return x;
}
const int N=5000+5;
vector<int> v[N],vis(N),par(N);
int f=0;
void dfs(int node,int p=0)
{
  if(f)
    return;
  vis[node]=1;
  par[node]=p;
  for(auto i:v[node])
  {
    if(f)
      return;
    if(i==p)
      continue;
    if(!vis[i])
      dfs(i,node);
    else
    {
      if(par[par[node]]==i)
      {
        f=1;
        cout<<i<<" "<<par[node]<<" "<<node;
        return;
      }
    }
  }
}

signed main() {
 ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);

 int n,x,y;
 cin>>n;
 string s;
 for(int i=1;i<=n;i++)
 {
  cin>>s;
  for(int j=0;j<n;j++)
  {
    if(s[j]=='1')
    {
      v[i].push_back(j+1);
    }
  }
 }
 for(int i=1;i<=n;i++)
 {
  if(!vis[i])
  {
    dfs(i);
  }
 }
 if(!f)
  cout<<-1;

}


#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
int mod=1e9+7;
int min(int a,int b){
  return (a<b)?a:b;
}
int max(int a,int b){
  return (a>b)?a:b;
}
int fp(int a,int b){
  if(b==0) return 1;
  int x=fp(a,b/2);
  x=(x*x)%mod;
  if(b&1) x=(x*a)%mod;
  return x;
}
const int N=5000+5;
vector<int> v[N],vis(N),par(N);
int f=0,a[N][N];
void dfs(int node,int p=0)
{
  if(f)
    return;
  vis[node]=1;
  par[node]=p;
  for(auto i:v[node])
  {
    if(f)
      return;
    if(i==p)
      continue;
    if(!vis[i])
      dfs(i,node);
    else
    {
      if(a[i][par[node]])
      {
        f=1;
        cout<<node<<" "<<i<<" "<<par[node];
        return;
      }
    }
  }
}

signed main() {
 ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);

 int n,x,y;
 cin>>n;
 string s;
 for(int i=1;i<=n;i++)
 {
  cin>>s;
  for(int j=0;j<n;j++)
  {
    if(s[j]=='1')
    {
      a[i][j+1]=1;
      v[i].push_back(j+1);
    }
    else
    {
      a[i][j+1]=0;
    }
  }
 }
 for(int i=1;i<=n;i++)
 {
  if(!vis[i])
  {
    dfs(i);
  }
 }
 if(!f)
  cout<<-1;

}


#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define int long long
int mod=1e9+7;
int min(int a,int b){
  return (a<b)?a:b;
}
int max(int a,int b){
  return (a>b)?a:b;
}
int fp(int a,int b){
  if(b==0) return 1;
  int x=fp(a,b/2);
  x=(x*x)%mod;
  if(b&1) x=(x*a)%mod;
  return x;
}
const int N=5000+5;
vector<int> v[N],vis(N),par(N);
int f=0,a[N][N];
void dfs(int node,int p=0)
{
  if(f)
    return;
  vis[node]=1;
  par[node]=p;
  for(auto i:v[node])
  {
    if(f)
      return;
    if(i==p)
      continue;
    if(!vis[i])
      dfs(i,node);
    else
    {
      if(par[par[node]]==i)
      {
        f=1;
        cout<<i<<" "<<par[node]<<" "<<node;
        return;
      }
      if(par[node]==par[i])
      {
        f=1;
        cout<<node<<" "<<i<<" "<<par[node];
        return;
      }
    }
  }
}

signed main() {
 ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);

 int n,x,y;
 cin>>n;
 string s;
 for(int i=1;i<=n;i++)
 {
  cin>>s;
  for(int j=0;j<n;j++)
  {
    if(s[j]=='1')
    {
      a[i][j+1]=1;
      v[i].push_back(j+1);
    }
    else
    {
      a[i][j+1]=0;
    }
  }
 }
 for(int i=1;i<=n;i++)
 {
  if(!vis[i])
  {
    dfs(i);
  }
 }
 if(!f)
  cout<<-1;

}


#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define int long long
int mod=1e9+7;
int min(int a,int b){
  return (a<b)?a:b;
}
int max(int a,int b){
  return (a>b)?a:b;
}
int fp(int a,int b){
  if(b==0) return 1;
  int x=fp(a,b/2);
  x=(x*x)%mod;
  if(b&1) x=(x*a)%mod;
  return x;
}
const int N=5000+5;
vector<int> v[N],vis(N),par(N);
int f=0,a[N][N];
void dfs(int node,int p=0)
{
  if(f)
    return;
  vis[node]=1;
  par[node]=p;
  for(auto i:v[node])
  {
    if(f)
      return;
    if(i==p)
      continue;
    if(!vis[i])
      dfs(i,node);
    else
    {
      if(a[i][par[node]])
      {
        f=1;
        cout<<node<<" "<<i<<" "<<par[node];
        return;
      }
    }
  }
}

signed main() {
 ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);

 int n,x,y;
 cin>>n;
 string s;
 for(int i=1;i<=n;i++)
 {
  cin>>s;
  for(int j=0;j<n;j++)
  {
    if(s[j]=='1')
    {
      a[i][j+1]=1;
      v[i].push_back(j+1);
    }
    else
    {
      a[i][j+1]=0;
    }
  }
 }
 for(int i=1;i<=n;i++)
 {
  if(!vis[i])
  {
    dfs(i);
  }
 }
 if(!f)
  cout<<-1;

}


#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define int long long
int mod=1e9+7;
int min(int a,int b){
  return (a<b)?a:b;
}
int max(int a,int b){
  return (a>b)?a:b;
}
int fp(int a,int b){
  if(b==0) return 1;
  int x=fp(a,b/2);
  x=(x*x)%mod;
  if(b&1) x=(x*a)%mod;
  return x;
}
const int N=5000+5;
vector<int> v[N],vis(N),par(N);
int f=0;
void dfs(int node,int p=0)
{
  if(f)
    return;
  vis[node]=1;
  par[node]=p;
  for(auto i:v[node])
  {
    if(f)
      return;
    if(i==p)
      continue;
    if(!vis[i])
      dfs(i,node);
    else
    {
      if(par[par[node]]==i)
      {
        f=1;
        cout<<i<<" "<<par[node]<<" "<<node;
        return;
      }
      if(par[par[i]]==node)
      {
        f=1;
        cout<<node<<" "<<par[i]<<" "<<i;
        return;
      }
    }
  }
}

signed main() {
 ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);

 int n,x,y;
 cin>>n;
 string s;
 for(int i=1;i<=n;i++)
 {
  cin>>s;
  for(int j=0;j<n;j++)
  {
    if(s[j]=='1')
    {
      v[i].push_back(j+1);
    }
  }
 }
 for(int i=1;i<=n;i++)
 {
  if(!vis[i])
  {
    dfs(i);
  }
 }
 if(!f)
  cout<<-1;

}


#include <bits/stdc++.h>
using namespace std;
int n, kol, used[6000], got;
char c;
stack <int> st;
vector <int> edge[6000];
void dfs(int v, int pred = -1)
{
	used[v] = 1;
	for(int i = 0; i < edge[v].size(); ++i)
	{
		int to = edge[v][i];
		if(used[to] == 2 || pred == to) continue;
		if(used[to] == 1)
		{
			got = 1;
			used[v] = 2;
			kol++;
			st.push(v);
			return;
		}
		dfs(to, v);
		if(got)
		{
			st.push(v);
			kol++;
			if(kol == 3)
			{
				while(st.size())
				{
					cout << st.top() << " ";
					st.pop();
				}
				exit(0);
			}
			return;
		}
	}
	used[v] = 2;
}
int main()
{
	cin >> n;
	for(int i = 1; i <= n; ++i)
	{
		for(int j = 1; j <= n; ++j)
		{
			cin >> c;
			if(i != j)
			{
				if(c == '1')
				{
					edge[i].push_back(j);
				}
			}
		}
	}
	for(int i = 1; i <= n; ++i)
	{
		if(used[i]) continue;
		dfs(i);
	}
	cout << -1;
}


#include <bits/stdc++.h>
using namespace std;
int n;
char a[5010][5010];
vector <int> vec, vec2, edge[5010];
int used[5010], cycle;
void answer()
{
	while(true)
	{
		for(int j = 0; j < vec.size() - 2; ++j)
		{
			if(a[vec[j]][vec[j + 2]] == '1')
			{
				cout << vec[j + 2] << " " << vec[j + 1] << " " << vec[j];exit(0);
			}
		}
		if(vec.size() == 4)
		{
			cout << vec[3] << " " << vec[2] << " " << vec[0];
			exit(0);
		}
		vec2.clear();
		for(int j = 0; j < vec.size(); j += 2)
		{
			vec2.push_back(vec[j]);
		}
		vec = vec2;
	}
	exit(0);
}
void dfs(int v)
{
	used[v] = 1;
	for(int i = 0; i < edge[v].size(); ++i)
	{
		int to = edge[v][i];
		if(used[to] == 2) continue;
		if(used[to] == 1)
		{
			cycle = 1;
			used[to] = 2;
			vec.push_back(v);
			return;
		}
		dfs(to);
		if(cycle)
		{
			vec.push_back(v);
			if(used[v] == 2)
			{
				answer();
			}
			return;
		}
	}
	used[v] = 2;
}
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for(int i = 1; i <= n; ++i)
	{
		for(int j = 1; j <= n; ++j)
		{
			cin >> a[i][j];
			if(a[i][j] == '1')
			{
				edge[i].push_back(j);
			}
		}
	}
	for(int i = 1; i <= n; ++i)
	{
		if(used[i]) continue;
		dfs(i);
	}
	cout << -1;
}


#include <bits/stdc++.h>
using namespace std;
int n;
char a[5010][5010];
vector <int> vec, vec2, edge[5010];
int used[5010], cycle;
void answer()
{
	while(true)
	{
		for(int j = 0; j < vec.size() - 2; ++j)
		{
			if(a[vec[j]][vec[j + 2]] == '1')
			{
				cout << vec[j + 2] << " " << vec[j + 1] << " " << vec[j];exit(0);
			}
		}
		vec2.clear();
		for(int j = 0; j < vec.size(); j += 2)
		{
			vec2.push_back(vec[j]);
		}
		vec = vec2;
	}
	exit(0);
}
void dfs(int v)
{
	used[v] = 1;
	for(int i = 0; i < edge[v].size(); ++i)
	{
		int to = edge[v][i];
		if(used[to] == 2) continue;
		if(used[to] == 1)
		{
			cycle = 1;
			used[to] = 2;
			vec.push_back(v);
			return;
		}
		dfs(to);
		if(cycle)
		{
			vec.push_back(v);
			if(used[v] == 2)
			{
				answer();
			}
			return;
		}
	}
	used[v] = 2;
}
int main()
{
	cin >> n;
	for(int i = 1; i <= n; ++i)
	{
		for(int j = 1; j <= n; ++j)
		{
			cin >> a[i][j];
			if(a[i][j] == '1')
			{
				edge[i].push_back(j);
			}
		}
	}
	for(int i = 1; i <= n; ++i)
	{
		if(used[i]) continue;
		dfs(i);
	}
	cout << -1;
}


#include <bits/stdc++.h>
using namespace std;
int n, kol, used[6000], got;
char c[5010][5010];
vector <int> vec;
vector <int> edge[6000];
void dfs(int v, int pred = -1)
{
	used[v] = 1;
	for(int i = 0; i < edge[v].size(); ++i)
	{
		int to = edge[v][i];
		if(used[to] == 2 || pred == to) continue;
		if(used[to] == 1)
		{
			got = 1;
			used[v] = 2;
			used[to] = 2;
			vec.push_back(v);
			return;
		}
		dfs(to, v);
		if(got)
		{
			vec.push_back(v);
			used[v] = 2;
			if(vec.size() >= 3 && c[vec[vec.size() - 3]][v] == '1')
			{
				cout << v << " " << vec[vec.size() - 2] << " " << vec[vec.size() - 3] << endl;
				exit(0);
			}
			return;
		}
	}
	used[v] = 2;
}
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for(int i = 1; i <= n; ++i)
	{
		for(int j = 1; j <= n; ++j)
		{
			cin >> c[i][j];
			if(i != j)
			{
				if(c[i][j] == '1')
				{
					edge[i].push_back(j);
				}
			}
		}
	}
	for(int i = 1; i <= n; ++i)
	{
		if(used[i]) continue;
		dfs(i);
	}
	cout << -1;
}


#include <bits/stdc++.h>
using namespace std;
int n, kol, used[6000], got;
char c;
vector <int> edge[6000];
void dfs(int v, int pred = -1)
{
	used[v] = 1;
	for(int i = 0; i < edge[v].size(); ++i)
	{
		int to = edge[v][i];
		if(used[to] == 2 || pred == to) continue;
		if(used[to] == 1)
		{
			got = 1;
			used[v] = 2;
			kol++;
			cout << v << " ";
			return;
		}
		dfs(to, v);
		if(got)
		{
			cout << v << " ";
			kol++;
			if(kol == 3)
			{
				exit(0);
			}
			return;
		}
	}
	used[v] = 2;
}
int main()
{
	cin >> n;
	for(int i = 1; i <= n; ++i)
	{
		for(int j = 1; j <= n; ++j)
		{
			cin >> c;
			if(i != j)
			{
				if(c == '1')
				{
					edge[i].push_back(j);
				}
			}
		}
	}
	for(int i = 1; i <= n; ++i)
	{
		if(used[i]) continue;
		dfs(i);
	}
	cout << -1;
}


#include <bits/stdc++.h>
using namespace std;
int n;
char a[5010][5010];
vector <int> vec, vec2, edge[5010];
int used[5010], cycle;
void answer()
{
	while(true)
	{
		for(int j = 0; j < vec.size() - 2; ++j)
		{
			if(a[vec[j]][vec[j + 2]] == '1')
			{
				cout << vec[j + 2] << " " << vec[j + 1] << " " << vec[j];exit(0);
			}
		}
		if(vec.size() == 4)
		{
			cout << vec[3] << " " << vec[2] << " " << vec[0];
			exit(0);
		}
		vec2.clear();
		for(int j = 0; j < vec.size(); j += 2)
		{
			vec2.push_back(vec[j]);
		}
		vec = vec2;
	}
	exit(0);
}
void dfs(int v)
{
	used[v] = 1;
	for(int i = 0; i < edge[v].size(); ++i)
	{
		int to = edge[v][i];
		if(used[to] == 2) continue;
		if(used[to] == 1)
		{
			cycle = 1;
			used[to] = 2;
			vec.push_back(v);
			return;
		}
		dfs(to);
		if(cycle)
		{
			vec.push_back(v);
			if(used[v] == 2)
			{
				answer();
			}
			return;
		}
	}
	used[v] = 2;
}
int main()
{
	cin >> n;
	for(int i = 1; i <= n; ++i)
	{
		for(int j = 1; j <= n; ++j)
		{
			cin >> a[i][j];
			if(a[i][j] == '1')
			{
				edge[i].push_back(j);
			}
		}
	}
	for(int i = 1; i <= n; ++i)
	{
		if(used[i]) continue;
		dfs(i);
	}
	cout << -1;
}