大致题意:
见http://www.nocow.cn/index.php/Translate:USACO/castle
大致思路:
苦逼模拟的并查集……usaco里面的还需要输出炸哪一堵墙……崩溃>_<
/*
ID:123ldss2
PROG: castle
LANG: C++
*/
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int nMax=100005;
int father[nMax],rank[nMax],N,M,num[nMax],sum; //rank近似树的高度。
int find(int x){ // 寻找父节点
if(x!=father[x])
return father[x]=find(father[x]);
return x;
}
void unite(int a,int b){
// cout<<a<<" unio "<<b<<endl;
int x=find(a);
int y=find(b);
if(x==y)
return ;
else{
if(rank[x]>rank[y]){
father[y]=x;
num[x]+=num[y];
}
else if(rank[x]<rank[y]){
father[x]=y;
num[y]+=num[x];
}
else{
father[x]=y;
num[y]+=num[x];
rank[y]++;
}
}
}
void set(){ // 初始化
int i;
for(i=0; i<nMax-1; i++){
father[i]=i;
rank[i]=0;
num[i]=1;
}
//n=0;
}
int map[100][100];
bool vis[nMax];
int main(){
int n,m,i,j,ans1,a,b;
// freopen ( "castle.in", "r", stdin );
// freopen ( "castle.out", "w", stdout );
while(scanf("%d%d",&n,&m)!=EOF){
set();
sum=0;
memset(vis,0,sizeof(vis));
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
scanf("%d",&map[i][j]);
if((map[i][j]&1)==0){
unite((i-1)*m+j,(i-1)*m+j-1);
}
if((map[i][j]&2)==0){
unite((i-1)*m+j,(i-2)*m+j);
}
if((map[i][j]&4)==0){
unite((i-1)*m+j,(i-1)*m+j+1);
}
if((map[i][j]&8)==0){
unite((i-1)*m+j,(i)*m+j);
}
}
}
ans1=0;
for(i=1;i<=n*m;i++){
j=find(i);
// cout<<"num"<<num[find(i)]<<endl;
ans1=max(ans1,num[find(i)]);
if(vis[j]==0){
vis[j]=1;
sum++;
}
}
cout<<sum<<endl;
cout<<ans1<<endl;
}
return 0;
}