#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int sj=510;
int n,m,hb[sj][sj],ans,mi,ma,e,ge;
bool kd[sj],jg[sj][sj];
inline int r()
{
int jg=0,jk=0;
jk=getchar()-‘0‘;
if(jk>=0&&jk<=9) jg+=jk;
jk=getchar()-‘0‘;
while(jk>=0&&jk<=9)
{
jg*=10;
jg+=jk;
jk=getchar()-‘0‘;
}
return jg;
}
void bj(int &x,int y)
{
x=x<y?x:y;
}
void db(int &x,int y)
{
x=x>y?x:y;
}
struct T
{
int le,ri;
}t[sj];
int comp(const T&a,const T&b)
{
if(a.le==b.le) return a.ri>b.ri;
return a.le<b.le;
}
void dfs1(int y,int x)
{
if(y<=0||y>n||x<=0||x>m) return;
if(y==n)
{
bj(mi,x);
db(ma,x);
}
if(hb[y][x]>hb[y+1][x]) dfs1(y+1,x);
if(hb[y][x]>hb[y-1][x]) dfs1(y-1,x);
if(hb[y][x]>hb[y][x+1]) dfs1(y,x+1);
if(hb[y][x]>hb[y][x-1]) dfs1(y,x-1);
}
void dfs2(int y,int x)
{
if(y<=0||y>n||x<=0||x>m) return;
jg[y][x]=1;
if(y==n)
kd[x]=1;
if(hb[y][x]>hb[y+1][x]&&!jg[y+1][x]) dfs2(y+1,x);
if(hb[y][x]>hb[y-1][x]&&!jg[y-1][x]) dfs2(y-1,x);
if(hb[y][x]>hb[y][x+1]&&!jg[y][x+1]) dfs2(y,x+1);
if(hb[y][x]>hb[y][x-1]&&!jg[y][x-1]) dfs2(y,x-1);
}
int main()
{
n=r();
m=r();
memset(hb,0x7f,sizeof(hb));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
hb[i][j]=r();
hb[1][0]=0;
hb[1][m+1]=0;
for(int i=1;i<=m;i++)
if(hb[1][i]>=hb[1][i+1]&&hb[1][i]>=hb[1][i-1])
dfs2(1,i);
for(int i=1;i<=m;i++)
if(!kd[i])
ge++;
if(ge!=0)
{
printf("0\n%d",ge);
return 0;
}
for(int i=1;i<=m;i++)
if(hb[1][i]>=hb[1][i+1]&&hb[1][i]>=hb[1][i-1])
{
mi=0x7fffffff;
ma=0;
dfs1(1,i);
if(ma!=0)
{
e++;
t[e].le=mi;
t[e].ri=ma;
}
}
sort(t+1,t+e+1,comp);
int yd,temp=0;
yd=t[1].ri;
ans=1;
for(int i=2;i<=e;i++)
{
if(t[i].le<=yd+1)
db(temp,t[i].ri);
if(t[i].le>yd+1)
{
yd=temp;
ans++;
if(t[i].le<=yd+1)
db(temp,t[i].ri);
}
}
if(yd<m)
ans++;
printf("1\n%d",ans);
return 0;
}