#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m,imap[51][51],ncon=0;
char cmap[51][51];
const int dx[9]={0,-1,-1,0,1,1,1,0,-1};
const int dy[9]={0,0,1,1,1,0,-1,-1,-1};
struct node {
int name1,name2,dis;
};
struct node edge[100011];
int fa[2501],num=0,ans=0;
int find(int x)
{
if(fa[x]==x) return x;
fa[x]=find(fa[x]);
return fa[x];
}
void big(int x,int y,int dis)
{
imap[x][y]=dis;
for(int i=1;i<=8;i++)
{
if(x+dx[i]>0&&x+dx[i]<=n&&y+dy[i]>0&&y+dy[i]<=m)
{
if(imap[x+dx[i]][y+dy[i]]==-1)
{
big(x+dx[i],y+dy[i],dis);
}
}
}
}
void edge_add(int from,int to,int dis)
{
num++;
edge[num].name1=from;
edge[num].name2=to;
edge[num].dis=dis;
}
void edge_find_up(int x,int y,int from,int dis)
{
if(y-1>0&&x-1>0) if(imap[x-1][y-1]!=0&&imap[x-1][y-1]!=from) edge_add(from,imap[x-1][y-1],dis);
if(y+1<=m&&x-1>0) if(imap[x-1][y+1]!=0&&imap[x-1][y+1]!=from) edge_add(from,imap[x-1][y+1],dis);
if(x-1>0)
{
if(imap[x-1][y]!=0&&imap[x-1][y]!=from) edge_add(from,imap[x-1][y],dis);
else if(imap[x-1][y]!=from) edge_find_up(x-1,y,from,dis+1);
}
}
void edge_find_down(int x,int y,int from,int dis)
{
if(y-1>0&&x+1<=n) if(imap[x+1][y-1]!=0&&imap[x+1][y-1]!=from) edge_add(from,imap[x+1][y-1],dis);
if(y+1<=m&&x+1<=n) if(imap[x+1][y+1]!=0&&imap[x+1][y+1]!=from) edge_add(from,imap[x+1][y+1],dis);
if(x+1<=n)
{
if(imap[x+1][y]!=0&&imap[x+1][y]!=from)
{
// printf("%d %d\n",x+1,y);
edge_add(from,imap[x+1][y],dis);
}
else if(imap[x+1][y]!=from) edge_find_down(x+1,y,from,dis+1);
}
}
void edge_find_lift(int x,int y,int from,int dis)
{
if(x-1>0&&y-1>0) if(imap[x-1][y-1]!=0&&imap[x-1][y-1]!=from) edge_add(from,imap[x-1][y-1],dis);
if(x+1<=n&&y-1>0) if(imap[x+1][y-1]!=0&&imap[x+1][y-1]!=from) edge_add(from,imap[x+1][y-1],dis);
if(y-1>0)
{
if(imap[x][y-1]!=0&&imap[x][y-1]!=from) edge_add(from,imap[x][y-1],dis);
else if(imap[x][y-1]!=from) edge_find_lift(x,y-1,from,dis+1);
}
}
void edge_find_right(int x,int y,int from,int dis)
{
if(x-1>0&&y+1<=m) if(imap[x-1][y+1]!=0&&imap[x-1][y+1]!=from) edge_add(from,imap[x-1][y+1],dis);
if(x+1<=n&&y+1<=m) if(imap[x+1][y+1]!=0&&imap[x+1][y+1]!=from) edge_add(from,imap[x+1][y+1],dis);
if(y+1<=m)
{
if(imap[x][y+1]!=0&&imap[x][y+1]!=from)
{
// printf("%d %d\n",x,y+1);
edge_add(from,imap[x][y+1],dis);
}
else if(imap[x][y+1]!=from) edge_find_right(x,y+1,from,dis+1);
}
}
void edge_build(int from,int x,int y)
{
if(x-1>0) edge_find_up(x-1,y,from,1);
if(x+1<=n) edge_find_down(x+1,y,from,1);
if(y-1>0) edge_find_lift(x,y-1,from,1);
if(y+1<=m) edge_find_right(x,y+1,from,1);
}
int cmp(struct node a,struct node b)
{
return a.dis<b.dis;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
cin>>cmap[i]+1;
for(int j=1;j<=m;j++)
{
if(cmap[i][j]==‘#‘) imap[i][j]=-1;
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(imap[i][j]==-1)
{
ncon++;
big(i,j,ncon);
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(imap[i][j]!=0) edge_build(imap[i][j],i,j);
}
}
sort(edge+1,edge+num+1,cmp);
int head=0,zh=0,xx,yy;
for(int i=1;i<=ncon;i++) fa[i]=i;
while(head<=ncon&&zh<=num)
{
zh++;
xx=find(edge[zh].name1),yy=find(edge[zh].name2);
if(xx!=yy)
{
ans+=edge[zh].dis;
fa[xx]=yy;
head++;
}
}
/*for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++) printf(" %d",imap[i][j]);
printf("\n");
}*/
printf("%d\n%d %d\n",ncon,head,ans);
return 0;
}