题意
给出一个 (h imes w) 的溜冰场,其中 #
表示地面,.
表示冰,并且溜冰场周围有一圈墙壁,人可以选择向东、南、西、北 (4) 个方向滑动,直到遇到墙壁或地面才停止。问最少需要增加几个地面,才能使得从任意位置出发,可以到达所有其它位置。((2≤H,W≤1000))
题目链接:https://atcoder.jp/contests/arc112/tasks/arc112_d
分析
分析清楚,答案就是连通块的个数(-1)。求连通块的个数时,一开始只考虑了行,没有考虑列,导致错误。
代码
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=1010;
char pic[N][N];
int fa[N<<1];
int Find(int x)
{
if(x!=fa[x])
return fa[x]=Find(fa[x]);
else return x;
}
void Merges(int x,int y)
{
int fx=Find(x),fy=Find(y);
if(fx!=fy)
fa[fx]=fy;
}
int main()
{
int h,w;
scanf("%d%d",&h,&w);
for(int i=1;i<=h;i++)
scanf("%s",pic[i]+1);
for(int i=1;i<=h+w;i++)
fa[i]=i;
Merges(1,h),Merges(1,h+1);
Merges(h+1,h+w),Merges(1,h+w);
for(int i=1;i<=h;i++)
{
for(int j=1;j<=w;j++)
{
if(pic[i][j]=='#')
Merges(i,j+h);
}
}
int ans=h+w+1;
set<int>st;
for(int i=1;i<=h;i++)
st.insert(Find(i));
ans=min(ans,int(st.size()));
st.clear();
for(int i=1;i<=w;i++)
st.insert(Find(i+h));
ans=min(ans,int(st.size()));
printf("%d
",ans-1);
return 0;
}
/*
.#.
...
...
...
*/