Advertisement
vlatkovski

joi open 2019 virus (kill me)

Jul 16th, 2019
385
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.59 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. using ll = long long;
  4. using pii = pair<int, int>;
  5.  
  6. string dumbbbb(int msk) {
  7.     string res = "{";
  8.     if (msk & 1) res += "N";
  9.     if (msk & 2) res += "E";
  10.     if (msk & 4) res += "S";
  11.     if (msk & 8) res += "W";
  12.     res += "}";
  13.     return res;
  14. }
  15.  
  16. const int inf  = 1e9;
  17. const int MAXM = 100010;
  18. const int MAXR = 810;
  19. const int MAXC = 810;
  20.  
  21. // N, E, S, W
  22. int dr[4] = {-1,  0,  1,  0};
  23. int dc[4] = { 0,  1,  0, -1};
  24.  
  25. int M, R, C;
  26.  
  27. inline int OPP(int d) {
  28.     return (d+2)%4;
  29. }
  30.  
  31. inline bool inside(int r, int c) {
  32.     return r >= 0 && r < R && c >= 0 && c < C;
  33. }
  34.  
  35. int U[MAXR][MAXC];
  36. int D[MAXM];
  37. int maxlen[1<<4]; // maximum length of subarray of (cyclic) D this mask is ok for
  38.  
  39. int bfscalls;
  40. bool infected[MAXR][MAXC];
  41. int timeinfected[MAXR][MAXC];
  42. int lastcheck[MAXR][MAXC];
  43. int cellmask[MAXR][MAXC]; // which neighbours are infected
  44.  
  45. bool adj[MAXR][MAXC][4];
  46.  
  47. int dfscalls;
  48. int num[MAXR][MAXC];
  49. int low[MAXR][MAXC];
  50. bool instk[MAXR][MAXC];
  51. vector<pii> stk;
  52.  
  53. int numscc;
  54. int sccid[MAXR][MAXC];
  55. vector<unordered_set<int>> sccadj;
  56. vector<int> sccsize, subtreesize;
  57. vector<bool> sccvisited;
  58.  
  59. void getmaskdata() {
  60.     for (int msk = 0; msk < (1<<4); ++msk) {
  61.         maxlen[msk] = 0;
  62.         int curlen = 0;
  63.         for (int i = 0; i < M; ++i) {
  64.             if (msk & D[i]) {
  65.                 ++curlen;
  66.             } else {
  67.                 curlen = 0;
  68.             }
  69.             maxlen[msk] = max(maxlen[msk], curlen);
  70.         }
  71.         if (curlen > 0) {
  72.             if (curlen == M) { // infinite cycle
  73.                 maxlen[msk] = inf;
  74.             } else {
  75.                 for (int i = 0; i < M; ++i) {
  76.                     if (msk & D[i]) {
  77.                         ++curlen;
  78.                     } else {
  79.                         break;
  80.                     }
  81.                 }
  82.                 maxlen[msk] = max(maxlen[msk], curlen);
  83.             }
  84.         }
  85.         // cout << "msk=" << dumbbbb(msk) << " maxlen=" << maxlen[msk] << endl;
  86.     }
  87. }
  88.  
  89. void bfs_expand(int r, int c, queue<pii>& q) {
  90.     for (int d = 0; d < 4; ++d) {
  91.         int r1 = r + dr[d], c1 = c + dc[d];
  92.         if (!inside(r1, c1)) continue;
  93.         if (lastcheck[r1][c1] < bfscalls) {
  94.             lastcheck[r1][c1] = bfscalls;
  95.             cellmask[r1][c1] = 0;
  96.         }
  97.         if (!(cellmask[r1][c1] & (1 << OPP(d)))) {
  98.             cellmask[r1][c1] |= (1 << OPP(d));
  99.             if (infected[r1][c1] && timeinfected[r][c] == timeinfected[r1][c1]) {
  100.                 cout << "(1) r=" << r << " c=" << c << " can visit d=" << dumbbbb(1<<d) << " r1=" << r1 << " c1=" << c1 << "\n";
  101.                 adj[r][c][d] = true;
  102.             } else {
  103.                 q.emplace(r1, c1);
  104.             }
  105.         }
  106.     }
  107. }
  108.  
  109. void bfs(int startrow, int startcol) {
  110.     cout << "bfs from (" << startrow << "," << startcol << ")\n";
  111.     ++bfscalls;
  112.     queue<pii> q;
  113.     infected[startrow][startcol] = true;
  114.     timeinfected[startrow][startcol] = bfscalls;
  115.     lastcheck[startrow][startcol] = bfscalls;
  116.     bfs_expand(startrow, startcol, q);
  117.     while (!q.empty()) {
  118.         pii top = q.front();
  119.         q.pop();
  120.         int r = top.first, c = top.second;
  121.         if (U[r][c] != 0 && maxlen[cellmask[r][c]] >= U[r][c]) {
  122.             infected[r][c] = true;
  123.             timeinfected[r][c] = bfscalls;
  124.             cout << "infected (" << r << "," << c << ")\n";
  125.             for (int d = 0; d < 4; ++d) {
  126.                 int r1 = r + dr[d], c1 = c + dc[d];
  127.                 if (inside(r1, c1) && timeinfected[r1][c1] == timeinfected[r][c] && adj[r1][c1][OPP(d)] == false) {
  128.                     cout << "(2) r=" << r << " c=" << c << " can be visited from d=" << dumbbbb(1<<OPP(d)) << " r1=" << r1 << " c1=" << c1 << "\n";
  129.                     adj[r1][c1][OPP(d)] = true;
  130.                 }
  131.             }
  132.             bfs_expand(r, c, q);
  133.         }
  134.     }
  135. }
  136.  
  137. void tarjan(int r, int c) {
  138.     num[r][c] = low[r][c] = dfscalls++;
  139.     instk[r][c] = true;
  140.     stk.emplace_back(r, c);
  141.     for (int d = 0; d < 4; ++d) {
  142.         if (!adj[r][c][d]) continue;
  143.         int r1 = r + dr[d], c1 = c + dc[d];
  144.         if (num[r1][c1] == -1) {
  145.             tarjan(r1, c1);
  146.         }
  147.         if (instk[r1][c1]) {
  148.             low[r][c] = min(low[r][c], low[r1][c1]);
  149.         }
  150.     }
  151.     if (low[r][c] == num[r][c]) {
  152.         ++numscc;
  153.         int SIZE = 0;
  154.         sccadj.push_back(unordered_set<int>());
  155.         sccvisited.push_back(false);
  156.         cout << "new SCC: ";
  157.         while (true) {
  158.             int r1 = stk.back().first, c1 = stk.back().second;
  159.             stk.pop_back();
  160.             ++SIZE;
  161.             instk[r1][c1] = false;
  162.             sccid[r1][c1] = numscc-1;
  163.             cout << "(" << r1 << "," << c1 << ") ";
  164.             if (r1 == r && c1 == c) {
  165.                 break;
  166.             }
  167.         }
  168.         sccsize.push_back(SIZE);
  169.         subtreesize.push_back(SIZE);
  170.         cout << endl;
  171.     }
  172. }
  173.  
  174. void sccdfs(int u) {
  175.     if (sccvisited[u]) return;
  176.     sccvisited[u] = true;
  177.     for (int v : sccadj[u]) {
  178.         sccdfs(v);
  179.         subtreesize[u] += subtreesize[v];
  180.     }
  181. }
  182.  
  183. int main() {
  184.     ios::sync_with_stdio(false); cin.tie(0);
  185.     int charmap[256];
  186.     charmap['N'] = 0, charmap['E'] = 1, charmap['S'] = 2, charmap['W'] = 3;
  187.     cin >> M >> R >> C;
  188.     for (int i = 0; i < M; ++i) {
  189.         char ch;
  190.         cin >> ch;
  191.         D[i] = (1 << (charmap[(int)ch]));
  192.     }
  193.     for (int i = 0; i < R; ++i) {
  194.         for (int j = 0; j < C; ++j) {
  195.             cin >> U[i][j];
  196. //            cout << "i=" << i << " j=" << j << " U=" << U[i][j] << endl;
  197.         }
  198.     }
  199.     getmaskdata();
  200.     memset(infected, false, sizeof(infected));
  201.     memset(lastcheck, 0, sizeof(lastcheck));
  202.     memset(cellmask, 0, sizeof(cellmask));
  203.     memset(adj, false, sizeof(adj));
  204.     bfscalls = 0;
  205.     for (int i = 0; i < R; ++i) {
  206.         for (int j = 0; j < C; ++j) {
  207.             if (U[i][j] != 0 && infected[i][j] == false) {
  208.                 bfs(i, j);
  209.             }
  210.         }
  211.     }
  212.     for (int i = 0; i < R; ++i) {
  213.         for (int j = 0; j < C; ++j) {
  214.             int m = 0;
  215.             for (int d = 0; d < 4; ++d) if (adj[i][j][d]) m |= (1<<d);
  216.             cout << "i=" << i << " j=" << j << " adj:" << dumbbbb(m) << endl;
  217.         }
  218.     }
  219.     numscc = 0;
  220.     memset(num, -1, sizeof(num));
  221.     memset(instk, false, sizeof(instk));
  222.     dfscalls = 0;
  223.     for (int r = 0; r < R; ++r) {
  224.         for (int c = 0; c < C; ++c) {
  225.             if (U[r][c] != 0 && num[r][c] == -1) {
  226.                 tarjan(r, c);
  227.             }
  228.         }
  229.     }
  230.     for (int r = 0; r < R; ++r) {
  231.         for (int c = 0; c < C; ++c) {
  232.             int u = sccid[r][c];
  233.             for (int d = 0; d < 4; ++d) {
  234.                 if (!adj[r][c][d]) continue;
  235.                 int r1 = r + dr[d], c1 = c + dc[d];
  236.                 int v = sccid[r1][c1];
  237.                 if (u != v) {
  238.                     sccadj[u].insert(v);
  239.                     cout << "scc edge: " << u << " -> " << v << endl;
  240.                 }
  241.             }
  242.         }
  243.     }
  244.     for (int r = 0; r < R; ++r) {
  245.         for (int c = 0; c < C; ++c) {
  246.             cout << sccid[r][c] << ' ';
  247.         }
  248.         cout << endl;
  249.     }
  250.     int minsize = 1e9, cnt = 0;
  251.     for (int u = 0; u < numscc; ++u) {
  252.         sccdfs(u);
  253.         int res = subtreesize[u];
  254.         if (res < minsize) {
  255.             minsize = res;
  256.             cnt = sccsize[u];
  257.         } else if (res == minsize) {
  258.             cnt += sccsize[u];
  259.         }
  260.         cout << "u=" << u << " res=" << res << endl;
  261.     }
  262.     cout << minsize << ' ' << cnt << endl;
  263. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement