#include <cstdio>
#include <cstring>
using namespace std;
int n,m,nm[505][505],vis[505][505];
int l[505][505],r[505][505];
/*
搜索当前点是否能到达目的点 并且回溯标记

l数组为 某个蓄水厂 走过的所有的城市的 最小 标记   能走到最左边的哪个 最靠近沙漠的城市
r数组为 某个蓄水厂 能走过的所有城市的 最大 标签 能走到最右边的哪个  最靠近沙漠的城市
初始化:最靠近的一排城市 l 和 r 从1-m
*/
int xx[4]={-1,0,1,0};
int yy[4]={0,1,0,-1};
int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a>b?b:a;}
void dfs(int x,int y){
    vis[x][y]=true;
    for(int i=0;i<4;i++){
        int xa=x+xx[i];
        int ya=y+yy[i];
        if(xa<1||xa>n||ya<1||ya>m)continue;
        if(nm[xa][ya]>=nm[x][y])continue;
        if(!vis[xa][ya])dfs(xa,ya);
        l[x][y]=min(l[x][y],l[xa][ya]);
        r[x][y]=max(r[x][y],r[xa][ya]);
    }
}
int main(){
    scanf("%d%d",&n,&m);
    memset(vis,0,sizeof(vis));
    memset(l,0x3f,sizeof(l));
    memset(r,0,sizeof(r));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&nm[i][j]);
    for(int i=1;i<=m;i++)l[n][i]=r[n][i]=i;
    for(int i=1;i<=m;i++)dfs(1,i);
    bool sf=false;
    int cnt=0;
    for(int i=1;i<=m;i++){
        if(!vis[n][i]){
            sf=true;
            cnt++;
        }
    }
    if(sf){
        printf("0\n%d",cnt);
        return 0;
    }
/*
按照题目要求,如果水无法流到每一个 接近沙漠的那一排城市中 ,则 输出 0 表示不能全部 流入
然后输出有多少个城市 没有流入水
*/
    int left=1;
/*
如:数据
3 6
8 4 5 6 4 4
7 3 4 3 3 3
3 2 2 1 1 2

l数组输出
1 2 2 2 5 5 
1 2 2 4 5 5 
1 2 3 4 5 5 

r数组输出
2 2 4 5 5 6 
2 2 4 4 5 6 
2 2 4 4 5 6 

初始值left为1
查找第一行 也就是接近湖泊的那一行 看看有蓄水池的水能到达 最接近 沙漠的城市 的 1号城市
如有 ,则看当前蓄水池能最多流到多少个最接近沙漠的城市 =>r数组
然后left更新至left+1,也就是表示 将要 求 是否有蓄水池 能流到left+1号城市
然后重复操作
*/
    while(left<=m){
        int mxr=0;
        for(int i=1;i<=m;i++)
            if(l[1][i]<=left){
                mxr=max(mxr,r[1][i]);
            }
            cnt++;
            left=mxr+1;
    }
    printf("1\n%d",cnt);
    return 0;
}