ARC112D - Skate【并查集】

题意

给出一个 \(h\times 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\n",ans-1);
    return 0;
}
/*
.#.
...
...
...
*/
posted @ 2021-02-15 11:02  xzx9  阅读(186)  评论(0编辑  收藏  举报