1. 程式人生 > >對於聯通塊的處理

對於聯通塊的處理

輸入格式 spa 集合 with 開始 接下來 重點 using false

01迷宮

題目描述

有一個僅由數字0與1組成的n×n格迷宮。若你位於一格0上,那麽你可以移動到相鄰4格中的某一格1上,同樣若你位於一格1上,那麽你可以移動到相鄰4格中的某一格0上。

你的任務是:對於給定的迷宮,詢問從某一格開始能移動到多少個格子(包含自身)。

輸入輸出格式

輸入格式:

輸入的第1行為兩個正整數n,m。

下面n行,每行n個字符,字符只可能是0或者1,字符之間沒有空格。

接下來m行,每行2個用空格分隔的正整數i,j,對應了迷宮中第i行第j列的一個格子,詢問從這一格開始能移動到多少格。

輸出格式:

輸出包括m行,對於每個詢問輸出相應答案。

輸入輸出樣例

輸入樣例:

2 2
01
10
1 1
2 2

輸出樣例1:

4
4

說明

所有格子互相可達。

對於20%的數據,$n≤10$;

對於40%的數據,$n≤50$;

對於50%的數據,$m≤5$;

對於60%的數據,$n≤100$,$m≤100$;

對於100%的數據,$n≤1000$,$m≤100000$。


對於這一到搜索題,怎麽搜索不是重點,重點是如何處理一個個聯通塊。

對於滿分數據,每次詢問遍歷一邊的是不可能的,這輩子都是不可能的。

我們可以染色或用並查集維護集合

這一道題它啟示我們,在處理擁有同一個性質的聯通塊時,要整塊整塊的處理

#include<iostream>
#include<queue>
using namespace std;
int dp[1010][1010],map[1010][1010];
bool exist[1010][1010];
int dx[4]={0,0,-1,1};
int dy[4]={-1,1,0,0};
int n,m,z;
queue<int>ox;
queue<int>oy;
int find(int x,int y)
{
    if(exist[x][y])
        return dp[x][y];
    exist[x][y]=true;
    int lx,ly;
    ox.push(x);oy.push(y);
    z++;
    for(int i=0;i<4;i++)
    {
        lx=x+dx[i];ly=y+dy[i];
        if(lx>0&&lx<=n&&ly>0&&ly<=n&&!exist[lx][ly]&&map[lx][ly]!=map[x][y])
            find(lx,ly);
    }
    return dp[x][y];
}
int main()
{
    cin.sync_with_stdio(false);
    cin>>n>>m;
    char input;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            cin>>input;
            map[i][j]=input-‘0‘;
            dp[i][j]=1;
        }
    int a,b;
    for(int i=1;i<=m;i++)
    {
        cin>>a>>b;
        find(a,b);
        z=max(z,dp[a][b]);
        cout<<z<<endl;
        while(!ox.empty())
        {
            dp[ox.front()][oy.front()]=z;
            ox.pop();oy.pop();
        }
        z=0;
    }
    return 0;
}

對於聯通塊的處理