二維並查集+bfs預處理

qduoj598

二維並查集+bfs預處理
要點:
1,將二維轉化爲一維
(11) (12) (13)
(21) (22) (23)
(31) (32) (33)
轉化爲:
1 2 3
4 5 6
7 8 9
計算函數:
int point(int x,int y)
{
    return (x-1)*m+y;
}
2,bfs進行預處理:
不用對所有的滿足mp[i][j]=='.'的點進行一次bfs,只需對
mp[i][j]=='.'並且是根結點的點進行一次bfs;
3,每一次‘#’變成‘.,只需訪問這個點的四周即可。
#include<map>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
const int num=5*1e3+10;
struct node
{
    int x,y;
    node(){};
    node(int a,int b)
    {
        x=a;y=b;
    }
};
int dp[num*num];
int pre[num*num];
char mp[num][num];
bool vis[num][num];
int n,m;
int point(int x,int y)
{
    return (x-1)*m+y;
}
int fa(int x)
{
    if(pre[x]!=x) return pre[x]=fa(pre[x]);
    return pre[x];
}
void merge(int s1,int s2)
{
    int tx=fa(s1);
    int ty=fa(s2);
    if(tx!=ty)
    {
        if(dp[tx]>=dp[ty])
        {
            dp[tx]+=dp[ty];
            pre[ty]=tx;
        }
        else
        {
            dp[ty]+=dp[tx];
            pre[tx]=ty;
        }
    }
    return ;
}
void bfs(int x,int y,int s)
{
    vis[x][y]=1;
    int nx[4]={0,0,1,-1};
    int ny[4]={1,-1,0,0};
    int tx,ty,s2;
    node t;
    queue<node>q;
    q.push(node(x,y));
    while(q.size())
    {
        t=q.front();q.pop();
        for(int i=0;i<4;i++)
        {
            tx=t.x+nx[i];
            ty=t.y+ny[i];
            if(vis[tx][ty]||tx>n||ty>m||tx<1||ty<1||mp[tx][ty]=='#') continue;
            vis[tx][ty]=1;
            s2=point(tx,ty);
            merge(s,s2);
            q.push(node(tx,ty));
        }
    }
    vis[x][y]=0;
    return ;
}
void int_i(void)
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            int t=point(i,j);
            pre[t]=t;
            if(mp[i][j]=='.')
                dp[t]=1;
        }
    }

    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            int t=point(i,j);
            if(mp[i][j]=='#'||pre[t]!=t) continue;
            bfs(i,j,t);
        }
    }
    return ;
}
int main()
{
    scanf("%d%d",&n,&m);
    getchar();
    for(int i=1;i<=n;i++)
        scanf("%s",mp[i]+1);

    int_i();
    int q,x,y;
    int nx[4]={1,-1,0,0};
    int ny[4]={0,0,-1,1};
    int tx,ty,f;
    scanf("%d",&q);
    while(q--)
    {
        scanf("%d%d",&x,&y);
        mp[x][y]='.';
        int s=point(x,y),s2;
        dp[s]=1;
        for(int i=0;i<4;i++)
        {
            tx=x+nx[i];
            ty=y+ny[i];
            if(tx<1||ty<1||tx>n||ty>m||mp[tx][ty]=='#') continue;
            s2=point(tx,ty);
            merge(s,s2);
        }
        f=fa(point(x,y));

        printf("%d\n",dp[f]);
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章