[Codeforces Round #634 (div3)]1335F - Robots on a Grid[拓扑排序][反向建图]

1335F - Robots on a Grid[拓扑排序][反向建图]

time limit per testmemory limit per testinputoutput
3 seconds256 megabytesstandard inputstandard output

Description:

There is a rectangular grid of size n × m n×m n×m. Each cell of the grid is colored black ( ′ 0 ′ ) ('0') (0) or white ( ′ 1 ′ ) ('1') (1). The color of the cell ( i , j ) (i,j) (i,j) is $c_{i,j}. You are also given a map of directions: for each cell, there is a direction s i , j s_{i,j} si,j which is one of the four characters ‘U’, ‘R’, ‘D’ and ‘L’.

  If s i , j s_{i,j} si,j is ‘U’ then there is a transition from the cell ( i , j ) (i,j) (i,j) to the cell ( i − 1 , j ) (i−1,j) (i1,j);
  if s i , j s_{i,j} si,j is ‘R’ then there is a transition from the cell ( i , j ) (i,j) (i,j) to the cell ( i , j + 1 ) (i,j+1) (i,j+1);
  if s i , j s_{i,j} si,j is ‘D’ then there is a transition from the cell ( i , j ) (i,j) (i,j) to the cell ( i + 1 , j ) (i+1,j) (i+1,j);
  if s i , j s_{i,j} si,j is ‘L’ then there is a transition from the cell ( i , j ) (i,j) (i,j) to the cell ( i , j − 1 ) (i,j−1) (i,j1).

It is guaranteed that the top row doesn’t contain characters ‘U’, the bottom row doesn’t contain characters ‘D’, the leftmost column doesn’t contain characters ‘L’ and the rightmost column doesn’t contain characters ‘R’.

You want to place some robots in this field (at most one robot in a cell). The following conditions should be satisfied.

  Firstly, each robot should move every time (i.e. it cannot skip the move). During one move each robot goes to the adjacent cell depending on the current direction.
  Secondly, you have to place robots in such a way that there is no move before which two different robots occupy the same cell (it also means that you cannot place two robots in the same cell). I.e. if the grid is “RL” (one row, two columns, colors does not matter there) then you can place two robots in cells ( 1 , 1 ) (1,1) (1,1) and ( 1 , 2 ) (1,2) (1,2), but if the grid is “RLL” then you cannot place robots in cells ( 1 , 1 ) (1,1) (1,1) and ( 1 , 3 ) (1,3) (1,3) because during the first second both robots will occupy the cell ( 1 , 2 ) (1,2) (1,2).

The robots make an infinite number of moves.

Your task is to place the maximum number of robots to satisfy all the conditions described above and among all such ways, you have to choose one where the number of black cells occupied by robots before all movements is the maximum possible. Note that you can place robots only before all movements.

You have to answer t independent test cases.

Input

The first line of the input contains one integer t ( 1 ≤ t ≤ 5 ⋅ 1 0 4 ) t (1≤t≤5⋅10^4) t(1t5104) — the number of test cases. Then t test cases follow.

The first line of the test case contains two integers n and m ( 1 < n m ≤ 1 0 6 ) (1<nm≤10^6) (1<nm106) — the number of rows and the number of columns correspondingly.

The next n n n lines contain m m m characters each, where the j j j-th character of the i i i-th line is c i , j c_{i,j} ci,j ( c i , j c_{i,j} ci,j is either ‘0’ if the cell ( i , j ) (i,j) (i,j) is black or ‘1’ if the cell ( i , j ) (i,j) (i,j) is white).

The next n n n lines also contain m m m characters each, where the j j j-th character of the i i i-th line is s i , j s_{i,j} si,j ( s i , j s_{i,j} si,j is ‘U’, ‘R’, ‘D’ or ‘L’ and describes the direction of the cell ( i , j ) (i,j) (i,j)).

It is guaranteed that the sum of the sizes of fields does not exceed 1 0 6 ( ∑ n m ≤ 1 0 6 ) 10^6 (∑nm≤10^6) 106(nm106).

Output

For each test case, print two integers — the maximum number of robots you can place to satisfy all the conditions described in the problem statement and the maximum number of black cells occupied by robots before all movements if the number of robots placed is maximized. Note that you can place robots only before all movements.


Example input

3
1 2
01
RL
3 3
001
101
110
RLL
DLD
ULL
3 3
000
000
000
RRD
RLD
ULL

Example output

2 1
4 3
2 2


分析:
题意:
一个 n × m n \times m n×m 的图, ′ 0 ′ '0' 0 为黑格子, ′ 1 ′ '1' 1 为白格子
每个格子上标有 U D R L UDRL UDRL 中其中一个字符
保证不会在最顶格为 U U U,最低格为 D D D,最左格为 L L L,最顶格为 R R R
可以在一些格子同时放机器人,每个格子一个时刻最多只能放一个机器人,
这些机器人会跟着格子给定的方向移动
问最多同时可以放多少个机器人
最多可以多少个机器人放在黑格子上

做法:
对于第二个样例,可以把图画出来看一看

可以发现,放的机器人最终走的位置会构成一个环
寻找环可以用拓扑排序

那么能放机器人的最大数量就是环的长度总和
而在环外并且能走到环内的位置,可以取模环长度得到他们相对的位置
问题在于怎么同时可以找这些点属于哪个环

拓扑排序中,非环上的点入度最后会减为 0 0 0
而环上的点入度会 > 0 > 0 >0
因此找环上的点是可以简单找到的
但是如果直接从环上点跑原图,是没有办法把连通的所有点都走一遍的
这个时候可以跑反向图

原本是环上的点我标记为同一种颜色
这样从环上的点开始跑 d f s dfs dfs 就可以遍历所有连在该环上的点
然后记录黑点深度,在进行深度取模长度就可以知道最多可以有多少个黑点

这题还可以用倍增的做法(还没学,留个坑,不知道会不会过来补)


Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;

int tx[4] = {-1, 1, 0, 0};
int ty[4] = {0, 0, -1, 1};

vector<int> red[maxn];
vector<int> ed[maxn];
queue<int> q;
bool vis[maxn];
int ind[maxn];
int dep[maxn];
bool mp[maxn];
char s[maxn];
int tot, len;

void topu() {
    while(!q.empty())   q.pop();
    for(int i = 0; i < tot; ++i)
        if(ind[i] == 0)
            q.push(i);
    while(!q.empty()) {
        int u = q.front(); q.pop();
        for(auto v : ed[u]) {
            ind[v] -= 1;
            if(ind[v] == 0) q.push(v);
        }
    }
}

void dfs(int u, int fa, int deep) {
    ind[u] = 0, dep[u] = deep;
    if(!mp[u])  q.push(u);
    for(auto v : red[u]) {
        if(dep[v])  len = dep[u];
        else        dfs(v, u, deep + 1);
    }
}

int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        int n, m, k = 0;
        scanf("%d%d", &n, &m);
        for(int i = 0; i < n; ++i) { // 0 black
            scanf("%s", s);
            for(int j = 0; j < m; ++j)
                mp[k++] = s[j] == '0' ? false : true;
        }
        int u, v;
        tot = n * m;
        for(int i = 0; i < tot; ++i)
            ind[i] = dep[i] = 0, ed[i].clear(), red[i].clear();
        for(int i = 0; i < n; ++i) {
            scanf("%s", s);
            for(int j = 0; j < m; ++j) {
                if(s[j] == 'U')         k = 0;
                else if(s[j] == 'D')    k = 1;
                else if(s[j] == 'L')    k = 2;
                else                    k = 3;
                u = i * m + j, v = u + tx[k] * m + ty[k];
                ed[u].push_back(v), red[v].push_back(u), ind[v] += 1;
                //cout << u << " " << v << endl;
            }
        }
        topu();
        int clen = 0, cblack = 0;
        for(int i = 0; i < tot; ++i) {
            if(ind[i] == 0)     continue;
            while(!q.empty())   q.pop();
            for(int j = 0; j < len; ++j)    vis[j] = false;
            len = 0;
            dfs(i, i, 1);
            while(!q.empty()) {
                int u = q.front(); q.pop();
                if(!vis[dep[u] % len]) {
                    cblack += 1;
                    vis[dep[u] % len] = true;
                }
            }
            clen += len;
        }
        printf("%d %d\n", clen, cblack);
    }
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值