#include <cstdio>
#include <vector>
#include <utility>
#include <vector>
#include <algorithm>
#include <iostream>
#include <cassert>

static const int MAXN = 1000;
static int DX[4] = {0, 1, 0, -1};
static int DY[4] = {1, 0, -1, 0};

using namespace std;

struct edge
{
    int c1, c2, v1, v2;

    edge() {}

    edge(int c1_, int c2_, int v1, int v2) :
        c1(min(c1_, c2_)),
        c2(max(c1_, c2_)),
        v1(v1),
        v2(v2)
    {}
};

int n, m;
int a[MAXN][MAXN];
int c[MAXN][MAXN];
bool used[MAXN][MAXN];
vector<int> weights;
vector<int> p, w;

bool inBounds(int x, int y)
{
    return (0 <= x) && (x < n) && (0 <= y) && (y < m);
}


static const int MAXK = MAXN * MAXN + 1;
int cnt[MAXK];
void count_sort(vector<edge>& v)
{
    edge *e = new edge[v.size()];
    for (int i = 0; i < MAXK; i++)
        cnt[i] = 0;
    for (int i = 0; i < v.size(); i++)
        cnt[v[i].c1]++;
    for (int i = 1; i < MAXK; i++)
        cnt[i] = cnt[i - 1] + cnt[i];
    for (int i = 0; i < v.size(); i++)
        e[--cnt[v[i].c1]] = v[i];
    for (int i = 0; i < MAXK; i++)
        cnt[i] = 0;
    for (int i = 0; i < v.size(); i++)
        cnt[v[i].c2]++;
    for (int i = 1; i < MAXK; i++)
        cnt[i] = cnt[i - 1] + cnt[i];
    for (int i = 0; i < v.size(); i++)
        v[--cnt[e[i].c2]] = e[i];
    delete[] e;
}

int fillWith, need;
int dfs(int x, int y)
{
    if (used[x][y])
        return 0;
    used[x][y] = true;
    c[x][y] = fillWith;
    int res = 1;
    for (int dir = 0; dir < 4; dir++)
    {
        int x2 = x + DX[dir];
        int y2 = y + DY[dir];
        if (!inBounds(x2, y2))
            continue;
        if (a[x2][y2] != need)
            continue;
        res += dfs(x2, y2);
    }
    return res;
}

int get(int v)
{
    return p[v] == v ? v : p[v] = get(p[v]);
}

edge e;
int ans = 0;
int c1ans, c2ans;
void unite(int v1, int v2)
{
    v1 = get(v1);
    v2 = get(v2);
    int root;
    if (v1 == v2)
        return;
    if (rand() & 1)
    {
        w[v1] += w[v2];
        p[v2] = v1;
        root = v1;
    } else {
        w[v2] += w[v1];
        p[v1] = v2;
        root = v2;
    }
    if (w[root] > ans)
    {
        ans = w[root];
        c1ans = e.c1;
        c2ans = e.c2;
    }
}

int main()
{
    freopen("death.in", "r", stdin);
    freopen("death.out", "w", stdout);
    scanf("%d %d", &n, &m);
    assert ((n <= 20) && (m <= 20));
    bool diff = false;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
        {
            scanf("%d", &a[i][j]);
            diff |= a[i][j] != a[0][0];
        }
    if (!diff)
    {
        printf("%d\n%d %d\n", n *m, a[0][0], a[0][0]);
        return 0;
    }
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            used[i][j] = false;
    int colors = 0;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            if (!used[i][j])
            {
                fillWith = colors++;
                need = a[i][j];
                weights.push_back(dfs(i, j));
            }
    vector<edge> edges;
    edges.reserve(2 * n * m);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            for (int dir = 0; dir < 4; dir++)
            {
                int x = i + DX[dir];
                int y = j + DY[dir];
                if (!inBounds(x, y))
                    continue;
                int c1 = c[i][j];
                int c2 = c[x][y];
                edges.push_back(edge(a[i][j], a[x][y], c1, c2));
            }
        }
    }
    count_sort(edges);
    p.resize(colors);
    w.resize(colors);

    for (int i = 0; i < colors; i++)
    {
        p[i] = i;
        w[i] = weights[i];
    }

    for (int left = 0; left < edges.size();)
    {
        int right = left;
        while (edges[left].c1 == edges[right].c1 && edges[left].c2 == edges[right].c2)
            right++;
        for (int i = left; i < right; i++)
        {
            e = edges[i];
            unite(e.v1, e.v2);
        }
        for (int i = left; i < right; i++)
        {
            e = edges[i];
            p[e.v1] = e.v1;
            p[e.v2] = e.v2;
            w[e.v1] = weights[e.v1];
            w[e.v2] = weights[e.v2];
        }
        left = right;
    }
    printf("%d\n", ans);
    printf("%d %d\n", c1ans, c2ans);
}
