#include <cstdio>
#include <vector>
#include <map>
#include <utility>
#include <vector>
#include <algorithm>
#include <set>
#include <iostream>

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

using namespace std;

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

vector<vector<pair<pair<int, int>, int> > > g;

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

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;
}

static const int USED2BITS = 25;
static const int USED2SIZE = 1 << USED2BITS;
static const int USED2SIZE1 = USED2SIZE - 1;
pair<pair<int, int>, int> used2_entries[USED2SIZE];
bool used2_used[USED2SIZE];
void used2_insert(const pair<pair<int, int>, int>& p)
{
    int hash = p.second * 21432 + p.first.first * 112739 + p.first.second * 81433;
    int pos = hash & USED2SIZE1;
    while (used2_used[pos] && used2_entries[pos] != p)
    {
        pos = (pos + 1) & USED2SIZE1;
    }
    used2_entries[pos] = p;
    used2_used[pos] = true;
}

bool used2_count(const pair<pair<int, int>, int>& p)
{
    int hash = p.second * 21432 + p.first.first * 112739 + p.first.second * 81433;
    int pos = hash & USED2SIZE1;
    while (used2_used[pos] && used2_entries[pos] != p)
    {
        pos = (pos + 1) & USED2SIZE1;
    }
    return used2_used[pos];
}

set<pair<pair<int, int>, int> > used2;

pair<int, int> needP;
int dfs2(int v)
{
    pair<pair<int, int>, int> p(needP, v);
    if (used2_count(p))
        return 0;
    used2_insert(p);
    int res = weights[v];
    while (true)
    {
        if (g[v].size() == 0)
            break;
        pair<pair<int, int>, int> last = g[v].back();
        if (last.first != needP)
            break;
        g[v].pop_back();
        res += dfs2(last.second);
    }
    return res;
}

pair<int, int> pack(int a, int b)
{
    if (a < b)
        return make_pair(a, b);
    else
        return make_pair(b, a);
}

int main()
{
    freopen("death.in", "r", stdin);
    freopen("death.out", "w", stdout);
    scanf("%d %d", &n, &m);
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
        {
            scanf("%d", &a[i][j]);
        }
    if (n == 1 && m == 1)
    {
        printf("1\n%d %d\n", 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));
            }
    g.resize(colors);
    map<pair<int, int>, vector<int> > verticesWithThisPair;
    vector<pair<int, int> > allPairs;
    allPairs.reserve(4 * 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];
                pair<int, int> p = pack(a[i][j], a[x][y]);
                g[c1].push_back(make_pair(p, c2));
                allPairs.push_back(p);
                verticesWithThisPair[p].push_back(c1);
            }
        }
    }
    sort(allPairs.begin(), allPairs.end());
    allPairs.resize(unique(allPairs.begin(), allPairs.end()) - allPairs.begin());
    reverse(allPairs.begin(), allPairs.end());
    for (int i = 0; i < colors; i++)
        sort(g[i].begin(), g[i].end());
    int ans = 0;
    pair<int, int> ansP;
    for (int i = 0; i < allPairs.size(); i++)
    {
        pair<int, int> p = allPairs[i];
        vector<int>& s = verticesWithThisPair[p];
        for (vector<int>::const_iterator it = s.begin(); it != s.end(); it++)
        {
            int v = *it;
            needP = p;
            int now = dfs2(v);
            if (now > ans)
            {
                ans = now;
                ansP = p;
            }
        }
    }
    printf("%d\n", ans);
    printf("%d %d\n", ansP.first, ansP.second);
}
