1335F - Robots on a Grid[拓扑排序][反向建图]
time limit per test | memory limit per test | input | output |
---|---|---|---|
3 seconds | 256 megabytes | standard input | standard 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) (i−1,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,j−1).
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(1≤t≤5⋅104) — 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<nm≤106) — 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(∑nm≤106).
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;
}