제출 #719827

#제출 시각아이디문제언어결과실행 시간메모리
719827finn__바이러스 (JOI19_virus)C++17
6 / 100
2055 ms79188 KiB
#include <bits/stdc++.h>
using namespace std;

#pragma GCC target("avx2")
#pragma GCC optimize("O3,unroll-loops")

constexpr size_t R = 800;
constexpr ptrdiff_t di[4] = {-1, 0, 1, 0}, dj[4] = {0, 1, 0, -1};

size_t r, c;
unsigned u[R][R], component[R][R], infection_time[1 << 4];
bitset<R> visited[R];
bitset<R * R> in_dfs;
vector<unsigned> adj[R * R];
vector<pair<size_t, size_t>> component_nodes[R * R];

inline bool is_implied_by(size_t i, size_t j, unsigned x)
{
    unsigned mask = 0;
    for (size_t k = 0; k < 4; k++)
        if (i + di[k] < r && j + dj[k] < c && component[i + di[k]][j + dj[k]] == x)
            mask |= 1 << k;
    return u[i][j] <= infection_time[mask];
}

inline void check_adj_vertices(size_t i, size_t j, unsigned x)
{
    for (size_t k = 0; k < 4; k++)
        if (i + di[k] < r && j + dj[k] < c && component[i + di[k]][j + dj[k]] != x &&
            is_implied_by(i + di[k], j + dj[k], x))
            adj[x].push_back(component[i + di[k]][j + dj[k]]);
}

unsigned merge_components(unsigned x, unsigned y)
{
    if (component_nodes[y].size() > component_nodes[x].size())
        swap(x, y);

    for (auto const &[i, j] : component_nodes[y])
        component[i][j] = x;
    for (auto const &[i, j] : component_nodes[y])
        check_adj_vertices(i, j, x);

    component_nodes[x].insert(component_nodes[x].end(), component_nodes[y].begin(), component_nodes[y].end());
    component_nodes[y].clear();
    adj[x].insert(adj[x].end(), adj[y].begin(), adj[y].end());
    adj[y].clear();
    return x;
}

pair<unsigned, unsigned> find_sccs(unsigned x)
{
    in_dfs[x] = 1;
    if (component_nodes[x].size() == 1)
        check_adj_vertices(x / R, x % R, x), visited[x / R][x % R] = 1;

    while (!adj[x].empty())
    {
        unsigned const y = adj[x].back();
        adj[x].pop_back();
        if (x == y)
            continue;
        if (in_dfs[y]) // Merge y into x.
        {
            unsigned nx = merge_components(x, y);
            in_dfs[x] = 0;
            return {y, nx};
        }

        auto [z, ny] = find_sccs(y);
        if (z != UINT_MAX)
        {
            if (z != x)
            {
                unsigned nx = merge_components(x, ny);
                in_dfs[x] = in_dfs[nx] = 0;
                return {z, nx};
            }
            in_dfs[x] = 0;
            x = ny;
            in_dfs[x] = 1;
        }
    }

    in_dfs[x] = 0;
    return {UINT_MAX, x};
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    size_t m;
    cin >> m >> r >> c;
    string d;
    cin >> d;
    for (size_t i = 0; i < m; i++)
        d[i] = d[i] == 'N' ? 0 : (d[i] == 'E' ? 1 : (d[i] == 'S' ? 2 : 3));
    for (size_t j = 0; j < 1 << 4; j++)
    {
        unsigned longest_conseq = 0;
        for (size_t i = 0; i < 2 * m; i++)
        {
            longest_conseq++;
            if (!(j & (1 << d[i % m])))
                longest_conseq = 0;
            infection_time[j] = max(infection_time[j], longest_conseq);
        }
        if (longest_conseq == 2 * m)
            infection_time[j] = UINT_MAX - 1;
    }

    for (size_t i = 0; i < r; i++)
        for (size_t j = 0; j < c; j++)
        {
            cin >> u[i][j];
            if (!u[i][j])
                u[i][j] = UINT_MAX;
        }

    for (size_t i = 0; i < R; i++)
        for (size_t j = 0; j < R; j++)
        {
            component[i][j] = i * R + j;
            if (u[i][j] != UINT_MAX)
                component_nodes[i * R + j].emplace_back(i, j);
        }

    for (size_t i = 0; i < r; i++)
        for (size_t j = 0; j < c; j++)
            if (!visited[i][j] && u[i][j] != UINT_MAX)
                find_sccs(i * R + j);

    unsigned min_scc_nodes = UINT_MAX, num_min_sccs = 0;
    for (unsigned i = 0; i < r; i++)
        for (unsigned j = 0; j < c; j++)
            if (!component_nodes[i * R + j].empty())
            {
                for (auto const &[x, y] : component_nodes[i * R + j])
                    check_adj_vertices(x, y, i * R + j);
                if (!adj[i * R + j].empty())
                    continue;
                if (component_nodes[i * R + j].size() < min_scc_nodes)
                    min_scc_nodes = component_nodes[i * R + j].size(), num_min_sccs = 1;
                else if (component_nodes[i * R + j].size() == min_scc_nodes)
                    num_min_sccs++;
            }

    cout << min_scc_nodes << '\n'
         << num_min_sccs * min_scc_nodes << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...