题目描述
奶牛们提出了一款创新性的新游戏,惊讶的是她们给这款游戏取了个最没创意的名字:“Moo”。 Moo游戏在一个由
在游戏结束的时候,每个格子中都包含一个数。在这个时刻,如果一头奶牛创建了一个由连通的格子组成的领域,大小不小于其他所有领域,那这头奶牛就获胜。一个“领域”被定义为一些具有相同数字编号的格子,其中每个在领域中的格子都直接与另一个同一领域中的格子通过上、下、左或者是右相邻(对角线不计)。
由于以单牛形式进行游戏有点无聊,奶牛们也对双牛组队进行游戏感兴趣。同一队的两头奶牛像之前一样可以创建一个领域,但是现在领域中的格子可以属于队伍中的任一头奶牛。
给定游戏棋盘的最终状态,请帮助奶牛们计算任何单头奶牛拥有的最大的领域包含的格子数量,以及任何两头奶牛组成的队伍占有的最大的领域包含的格子的数量。两头奶牛占有的领域必须要同时包含队伍中两头奶牛的编号,不能仅仅包含一头。
输入输出格式
输入格式:
输入的第一行包含
输出格式:
输出的第一行描述任何单头奶牛占有的最大领域大小,第二行描述任何两头奶牛的队伍占有的最大领域的大小。
输入输出样例
4
2 3 9 3
4 9 9 1
9 9 1 7
2 1 1 9
5
10
说明
在这个例子中,单头奶牛占有的最大领域是由五个9组成的。如果编号为1和9的奶牛组队,她们可以形成一个大小为10的领域。
题解: 第一个数很好算,DFS一边就行,并给每一个联通块序列化,然后在for扫一遍将建立关系,因为可能会出现重复,所以用set去重一下,然后枚举一个点到另一点,DFS ,删除经过的边。因为每一次DFS需要标记点,不能每一次都初始化,可以用一个栈存储,每一次搜索完后,对栈的中标记的数操作。
c++ code:
#include <bits/stdc++.h>
#define IT set<Node>::iterator
using namespace std;
const int N =300 + 10;
int mmap[N][N],flag[N][N],num[N*N],dig[N*N];
bool vis[N][N],vised[N*N];
int cnt;
int dir[4][2]={1,0,0,1,0,-1,-1,0},tot,n,cot,head[N*N*4];
stack<int>sta;
struct Edge{
int to,next,flag;
}edge[N*N*4];
void add(int u,int v)
{
edge[cot].next=head[u];
edge[cot].to=v;
edge[cot].flag = 1;
head[u]=cot++;
}
struct Node{
int u,v;
bool operator<(const Node &b) const
{
return u == b.u?v < b.v:u < b.u;
}
};
set<Node>s;
int dfs(int x,int y)
{
int ans = 0;
vis[x][y] = true;
flag[x][y] = tot;
for(int i = 0;i < 4;i++)
{
int dx = x + dir[i][0],dy = y + dir[i][1];
if(dx >= 1 && dx <= n && dy >= 1 && dy <= n && !vis[dx][dy] && mmap[x][y] == mmap[dx][dy])
ans += dfs(dx,dy) + 1;
}
return ans;
}
void LK()
{
for(int i = 1;i <= n;i++)
for(int j = 1;j <= n;j++)
{
for(int k = 0;k < 4;k++)
{
int dx = i + dir[k][0],dy = j + dir[k][1];
Node now;
if(dx >= 1 && dx <= n && dy >= 1 && dy <= n && flag[i][j] != flag[dx][dy])
{
now.u = flag[dx][dy];now.v = flag[i][j];
if(now.u > now.v)
swap(now.u,now.v);
s.insert(now);
}
}
}
}
int dfs(int now,int val1,int val2)
{
int ans = num[now];
vised[now] = true;
sta.push(now);
for(int i=head[now];i != -1;i = edge[i].next)
{
int to = edge[i].to;
if(!vised[to] && (dig[to] == val1 || dig[to] == val2) && edge[i].flag)
{
edge[i].flag = 0;
ans += dfs(to,val1,val2);
}
}
return ans;
}
int solve(int now)
{
int ans = 0;
for(int i=head[now];i != -1;i = edge[i].next)
{
int to = edge[i].to;
if(!vised[to] && edge[i].flag)
{
int val = dfs(now,dig[to],dig[now]);
ans = max(val,ans);
while(!sta.empty())
vised[sta.top()] = false,sta.pop();
}
}
vised[now] = true;
return ans;
}
int main()
{
tot = 0;cot = 0;
memset(vis,false,sizeof(vis));
memset(flag,0,sizeof(flag));
for(int i = 0; i < N*N*4;i++)
head[i] = -1;
scanf("%d",&n);
for(int i = 1;i <= n;i++)
for(int j = 1;j <= n;j++)
scanf("%d",&mmap[i][j]);
int ans = 0,ant = 0;
for(int i = 1;i <= n;i++)
for(int j = 1;j <= n;j++)
if(!vis[i][j])
{
++tot;
int val = dfs(i,j)+1;
ans = max(ans,val);
num[tot] = val;
dig[tot] = mmap[i][j];
}
LK();
Node node;
for(IT it = s.begin();it != s.end();it++)
{
node = *it;
add(node.u,node.v);
add(node.v,node.u);
}
memset(vised,false,sizeof(vised));
for(int i = 1;i <= tot;i++)
ant = max(ant,solve(i));
printf("%d\n%d\n",ans,ant);
return 0;
}