CSU2015 Artwork Problem Solution (BFS+ Union Check)

See the original title: title portal

The meaning of the title: Given a matrix white block of n*m (1<=n, m<=1000), then enter q (1<=q<=1e4) pairs of nodes, each pair of nodes is in the same row or the same Columns (nodes on the line segment where the two nodes are connected are also connected), blacken all the white nodes (including both ends) on the connection line of these node pairs. After each blacking, it is required to output the number of white connected blocks in the matrix at this time

(Um... I feel that the ability to summarize is not good at all, it is better to look at the question directly...)

enter:

first line: nmq

Go down q lines: x1 y1 x2 y2

(x1, y1) and (x2, y2) are the two endpoints that will be blacked out, and the input ensures that x1==x2 or y1==y2

Output: q rows, the number of white connected blocks in the matrix after each blackout

Time limit: 4s

A simple analysis: the conventional thinking is to input a group, and then find the number of white connected blocks once, however, just calculate the complexity, DFS or BFS to find the connected blocks, the complexity is almost n*m, and then q times of query, also It is O(n*m*q), which is about 1e3*1e3*1e4=1e10. 4s? does not exist~ Then, if I am not good at graph theory, I will not be able - but I have teammates - this guy This question is the third time. . .

A wave of halal analysis: since thinking forward, inputting it once, and calculating it once is not enough, then do the reverse calculation~ Write down the two endpoints of each connection, and mark the time stamp of the first blackout, that is, the number of times It is blacked out~ Then we directly calculate how many white connected blocks there are in the last time. The complexity of this step is O(n*m), and then we paint it in reverse again and again to see if it constitutes a new one every time we paint white. The connection block of , or whether different connection blocks are connected together after whitening, the worst complexity of this step is O(m) or O(n). Calculate, q times, which is O(n*q), so the total complexity is also O(n*m+n*q), which is a complexity of the order of 1e7, perfect~

Then there is the code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;

struct point
{
    int x, y;
    point(int X = 0, int Y = 0):x(X), y(Y) {};
    void read()
    {
        scanf("%d%d", &x, &y);
    }
    bool operator==(const point& c) const
    {
        return x == c.x && y == c.y;
    }
};//Structure: point
struct line
{
    point x, y;
    void read()
    {
        x.read();
        y.read();
    }
}h[10010];//Structure: two points, record the two endpoints of each blackout
point dad[1001][1001];//Record the parent node of each point
point father(point p)//Update the parent node
{
    if(p == dad[p.x][p.y])      return p;
    return dad[p.x][p.y] = father(dad[p.x][p.y]);
}
int t[1001][1001]; //Record the timestamp of the first blackout of each node
int cnt[10010]; //Record the number of Unicom blocks for each query
bool used[1001][1001]; //BFS determines whether (i,j) has been accessed when seeking the connection block
intmain()
{
    #ifdef AFei
    freopen("in.txt", "r", stdin);
    #endif // AFei
    int n, m, q;
    scanf("%d%d%d", &n, &m, &q);
    memset(t, -1, sizeof t);// t[i][j]==-1 means (i,j) point is white~
    for(int i = 0; i < q; ++ i)
    {
        h[i].read();//Read in the two endpoints of each blacked-out line segment

        int xl = min(h[i].x.x, h[i].y.x)-1, xr = max(h[i].x.x, h[i].y.x)-1;
        int yl = min(h[i].x.y, h[i].y.y)-1, yr = max(h[i].x.y, h[i].y.y)-1;
        for(int j = xl; j <= xr; ++ j)//Record when a point is blacked out
            for(int k = yl; k <= yr; ++ k)
                if(t[j][k] == -1)
                    t[j][k] = i;
    }

    for(int i = 0; i < n; ++ i)
        for(int j = 0; j < m; ++ j)
        {
            dad[i][j] = point(i, j);//Initially, each point is considered to be a connected block, and they take themselves as the parent node
        }

    / / Find the final number of Unicom blocks
    cnt[q-1] = 0;
    int row[4] = {0, 0, 1, -1};
    int col[4] = {1, -1, 0, 0};

    for(int i = 0; i < n; ++ i)
    {
        for(int j = 0; j < m; ++ j)
        {
            if(t[i][j] == -1 && father(point(i, j)) == point(i, j))//BFS finds the connecting block, the parent node of the entire connecting block is (i ,j)
            {
                point d = point(i, j);
                cnt[q-1]++;
                queue<point> Q;
                Q.push(d);
                while(!Q.empty())
                {
                    point next = Q.front();
                    Q.pop();
                    for(int k = 0; k < 4; ++ k)
                    {
                        int nX = next.x + row[k], nY = next.y + col[k];
                        if(nX >= 0 && nX < n && nY >= 0 && nY < m && used[nX][nY] == 0 && t[nX][nY] == -1)
                        {//The point in the range, and has not been visited, and is the point of the white block
                            used[nX][nY] = 1;
                            Q.push(point(nX, nY));
                            dad[nX][nY] = point(i, j);
                        }
                    }
                }
            }
        }
    }

    for(int i = q-1; i; -- i)//Reverse solution
    {
        cnt[i-1] = cnt[i];//cnt[i] is the solution of the i-th query, i starts from 0

        int xl = min(h[i].x.x, h[i].y.x)-1, xr = max(h[i].x.x, h[i].y.x)-1;
        int yl = min(h[i].x.y, h[i].y.y)-1, yr = max(h[i].x.y, h[i].y.y)-1;

        for(int j = xl; j <= xr; ++ j)
            for(int k = yl; k <= yr; ++ k)
            {
                if(t[j][k] == i)//If (j,k) is blacked out at the i-th time
                {
                    t[j][k] = -1;//Forcibly white
                    point P[4] = {point(-1, -1), point(-1, -1), point(-1, -1), point(-1, -1)};
                        //Record the parent node of (j,k) up, down, left and right points,

                    bool flag = 0;//Determine whether there are black blocks around
                    //As long as there is a white block in one direction up, down, left and right, connect (j, k) to the connected block to which the white block belongs
                    if(j && t[j-1][k] == -1)
                        flag = 1, dad[j][k] = P[0] = father(point(j-1, k));
                    if(k && t[j][k-1] == -1)
                        flag = 1, dad[j][k] = P[1] = father(point(j, k-1));
                    if(j < n-1 && t[j+1][k] == -1)
                        flag = 1, dad[j][k] = P[2] = father(point(j+1, k));
                    if(k < m-1 && t[j][k+1] == -1)
                        flag = 1, dad[j][k] = P[3] = father(point(j, k+1));

                    if(!flag)//If there are black blocks all around, then the Unicom block +1
                        cnt[i-1] ++;
                    else
                    {
                        for(int z = 0; z < 4; ++ z)//traverse four directions
                        {
                            if(P[z] == point(-1, -1))//If this direction is not a white block
                                continue;

                            if(!(father(P[z]) == father(point(j, k))))//Two different connected blocks are connected because (j, k) is painted white
                            {
                                cnt[i-1] --;//The total number of Unicom blocks -1
                                dad[P[z].x][P[z].y] = father(point(j, k));//Update the parent node
                            }
                        }
                    }
                }
            }
    }

    for(int i = 0; i < q; ++ i)
        printf("%d\n", cnt[i]);
    return 0;
}


在135行,if(!(father(P[z]) == father(point(j, k))))

I started by writing if(!(P[z] == father(point(j, k))))

Then wa, this bug stuck for a long time, I don't know why. . . Remember first, and come back to see later~

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326048894&siteId=291194637