This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <iostream>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cassert>
using namespace std;
#ifdef LOCAL_DEBUG
#include <local_debug.h>
#define DEBUG(...) DBG2::cprint(#__VA_ARGS__, __LINE__, __VA_ARGS__)
#else
#define DEBUG(...)
#endif
using VI = vector<int>;
using VVI = vector<VI>;
int M, R, C;
string D;
int U[801][801];
int max_runs[1<<4];
const string DIR = "NESW";  // direction wind blows from
int dr[] = {-1,  0, +1,  0};
int dc[] = { 0, +1,  0, -1};
void dfs1(const VVI& G, VI& vis, stack<int>& S, int u) {
   vis[u] = true;
   for (int v : G[u]) {
      if (!vis[v])
         dfs1(G, vis, S, v);
   }
   S.push(u);
}
void dfs2(const VVI& G, VI& vis, VI& comp, int u) {
   vis[u] = true;
   comp.push_back(u);
   for (int v : G[u]) {
      if (!vis[v])
         dfs2(G, vis, comp, v);
   }
}
const int INF = 1e9 + 123;
int infected_mask[801][801];
int bfs(const VI& sources, VI& vis, const VI& COMP_IDs, int comp_id, VI& ans) {
   queue<int> q;
   for (int src : sources) {
      if (U[src / C][src % C] == 0)
         return INF;
      q.push(src);
   // assert( vis[src] >= comp_id );
      vis[src] = comp_id;
   }
   VI visited_nodes;
   while (!q.empty()) {
      int u = q.front(); q.pop();
      visited_nodes.push_back(u);
   //   assert(cnt < R*C*2);
      int r = u/C, c = u % C;
      for (int d = 0; d < 4; ++d) {
         int nr = r + dr[d], nc = c + dc[d];
         if (nr < 0 or nr >= R or nc < 0 or nc >= C)
            continue;
         if (U[nr][nc] == 0)
            continue;
         int nmask = infected_mask[nr][nc] |= 1<<((d+2)%4);
         if ( max_runs[nmask] < U[nr][nc] )
            continue;
         int v = nr * C + nc;
         if (COMP_IDs[v] > comp_id)
            return INF;
         if (vis[v] != comp_id) {
            q.push(v);
            vis[v] = comp_id;
         }
      }
   }
   
   int res = visited_nodes.size();
   for (int u : visited_nodes)
      ans[u] = min(ans[u], res);
   
   return res;
}
int main(int argc, char* argv[]) {
   ios_base::sync_with_stdio(false); 
   cin.tie(nullptr);
   cin >> M >> R >> C;
   cin >> D;
   for (int r = 0; r < R; ++r)
      for (int c = 0; c < C; ++c)
         cin >> U[r][c];
   D += D;
   auto matches = [](int mask, char c) -> bool {
      size_t d = DIR.find(c);
      assert(d != string::npos);
      return (mask & (1<<d)) != 0;
   };
   for (int mask = (1<<4)-1; mask > 0; --mask) {
      for (int k = 0, run = 0; k <= 2*M; k++) {
         if (k == 2*M or not matches(mask, D[k])) {
            max_runs[mask] = max(max_runs[mask], run);
            run = 0;
         }
         else
            ++run;
      }
   // DEBUG(mask, max_runs[mask]);
   }
   const int NUM_NODES = R*C;
   auto NODE_ID = [](int r, int c) -> int {
      return r*C + c;
   };
   VVI G(NUM_NODES);
   for (int r = 0; r < R; ++r) {
      for (int c = 0; c < C; ++c) {
         if (U[r][c] == 0) continue;
         for (int d = 0; d < 4; ++d) {
            if (U[r][c] > max_runs[1<<d])
               continue;
            int pr = r + dr[d], pc = c + dc[d];
            if (pr < 0 or pr >= R or pc < 0 or pc >= C or U[pr][pc] == 0)
               continue;
            G[NODE_ID(pr, pc)].push_back(NODE_ID(r, c));
         }
      }
   }
   VI vis(NUM_NODES, false);
   stack<int> S;
   for (int src = 0; src < NUM_NODES; ++src)
      if (!vis[src])
         dfs1(G, vis, S, src);
   VVI Grev(NUM_NODES);
   for (int u = 0; u < NUM_NODES; ++u)
      for (int v : G[u])
         Grev[v].push_back(u);
   vis = VI(NUM_NODES, false);
   VVI SCC;
   VI COMP_IDs(NUM_NODES, -1);
   while (!S.empty()) {
      int u = S.top(); S.pop();
      if (!vis[u]) {
         VI comp;
         dfs2(Grev, vis, comp, u);
         int comp_id = SCC.size();
         for (int u : comp)
            COMP_IDs[u] = comp_id;
         SCC.push_back(comp);
      }
   }
   auto is_root = [&](int comp_id) -> bool {
      for (int u : SCC[comp_id])
         for (int v : G[u])
            if (COMP_IDs[v] > COMP_IDs[u])
               return false;
      return true;
   };
   
   int best_count = INF;
   VI ans(NUM_NODES, INF);
   vis = VI(NUM_NODES, INF);
   for (int comp_id = int(SCC.size()) - 1; comp_id >= 0; comp_id--) {
      /*
      cerr << comp_id << ":";
      for (int u : SCC[comp_id])
         cerr << " (" << u/C << ',' << u%C << ")";
      cerr << endl;
      */
      if (is_root(comp_id)) {
         int cnt = bfs( SCC[comp_id], vis, COMP_IDs, comp_id, ans );
      //   DEBUG(comp_id, cnt);
         if (best_count > cnt) {
            best_count = cnt;
         }
      }
   }
   cout << best_count << '\n';
   cout << count(ans.begin(), ans.end(), best_count) << '\n';
   
   return 0;
}
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |