EntropyIncreaser

[BJOI2018] Kakuro

Mar 19th, 2018
221
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.44 KB | None | 0 0
  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <cstring>
  4.  
  5. #include <algorithm>
  6. #include <limits>
  7. #include <queue>
  8.  
  9. #define LOG(FMT...) // fprintf(stderr, FMT)
  10.  
  11. using namespace std;
  12.  
  13. typedef long long ll;
  14.  
  15. struct Num {
  16.     ll d, infs;
  17.  
  18.     Num(ll d = 0, ll infs = 0) : d(d), infs(infs) {}
  19.  
  20.     bool operator<(const Num& x) const {
  21.         if (infs != x.infs)
  22.             return infs < x.infs;
  23.         return d < x.d;
  24.     }
  25.  
  26.     Num operator+(const Num& x) const {
  27.         return Num(d + x.d, infs + x.infs);
  28.     }
  29.  
  30.     Num operator*(ll x) const {
  31.         return Num(d * x, infs * x);
  32.     }
  33.  
  34.     friend Num operator*(ll x, const Num& y) {
  35.         return y * x;
  36.     }
  37.  
  38.     Num& operator+=(const Num& x) {
  39.         d += x.d;
  40.         infs += x.infs;
  41.         return *this;
  42.     }
  43. };
  44.  
  45. struct Edge {
  46.     int v, w;
  47.     Num c;
  48.     Edge *next, *rev;
  49. };
  50.  
  51. const int N = 32, V = N * N, T = V - 1, S = V - 2;
  52. const Num INF = Num(0, 1);
  53.  
  54. int n, m, nCnt;
  55. int typ[N][N];
  56. int a[N][N][2];
  57. int fromRow[N][N];
  58. Num cst[N][N][2];
  59.  
  60. bool inq[V];
  61. Edge* pth[V];
  62. Num dist[V];
  63.  
  64. Edge* g[V];
  65.  
  66. Edge* addEdge(int u, int v, int w, const Num& c);
  67. void link(int u, int v, int w, const Num& c);
  68. Num mcf();
  69. bool spth();
  70.  
  71. int main() {
  72.     scanf("%d%d", &n, &m);
  73.     for (int i = 1; i <= n; ++i)
  74.         for (int j = 1; j <= m; ++j)
  75.             scanf("%d", &typ[i][j]);
  76.     for (int i = 1; i <= n; ++i)
  77.         for (int j = 1; j <= m; ++j) {
  78.             if ((typ[i][j] & 1) || typ[i][j] == 4)
  79.                 scanf("%d", &a[i][j][0]);
  80.             if (typ[i][j] & 2)
  81.                 scanf("%d", &a[i][j][1]);
  82.         }
  83.     for (int i = 1; i <= n; ++i)
  84.         for (int j = 1; j <= m; ++j) {
  85.             int x;
  86.             if ((typ[i][j] & 1) || typ[i][j] == 4) {
  87.                 scanf("%d", &x);
  88.                 if (x == -1)
  89.                     cst[i][j][0] = INF;
  90.                 else
  91.                     cst[i][j][0] = x;
  92.             }
  93.             if (typ[i][j] & 2) {
  94.                 scanf("%d", &x);
  95.                 if (x == -1)
  96.                     cst[i][j][1] = INF;
  97.                 else
  98.                     cst[i][j][1] = x;
  99.             }
  100.         }
  101.     Num curCost = 0;
  102.     for (int i = 1; i <= n; ++i)
  103.         for (int j = 1; j <= m; ++j) {
  104.             if (typ[i][j] & 2) {
  105.                 ++nCnt;
  106.                 int cnt = 0, orij = j;
  107.                 for (++j; typ[i][j] == 4; ++j) {
  108.                     fromRow[i][j] = nCnt;
  109.                     ++cnt;
  110.                 }
  111.                 int used = abs(a[i][orij][1] - cnt);
  112.                 curCost += used * cst[i][orij][1];
  113.                 if (a[i][orij][1] > cnt)
  114.                     link(S, nCnt, used, cst[i][orij][1] * -1);
  115.                 link(S, nCnt, numeric_limits<int>::max(), cst[i][orij][1]);
  116.                 --j;
  117.             }
  118.         }
  119.     for (int j = 1; j <= m; ++j)
  120.         for (int i = 1; i <= n; ++i)
  121.             if (typ[i][j] & 1) {
  122.                 ++nCnt;
  123.                 int cnt = 0, orii = i;
  124.                 for (++i; typ[i][j] == 4; ++i) {
  125.                     int used = abs(a[i][j][0] - 1);
  126.                     curCost += used * cst[i][j][0];
  127.                     ++cnt;
  128.                     link(fromRow[i][j], nCnt, used, cst[i][j][0] * -1);
  129.                     link(fromRow[i][j], nCnt, numeric_limits<int>::max(), cst[i][j][0]);
  130.                 }
  131.                 int used = abs(a[orii][j][0] - cnt);
  132.                 curCost += used * cst[orii][j][0];
  133.                 if (a[orii][j][0] > cnt)
  134.                     link(nCnt, T, used, cst[orii][j][0] * -1);
  135.                 link(nCnt, T, numeric_limits<int>::max(), cst[orii][j][0]);
  136.                 --i;
  137.             }
  138.     LOG("%lld %lld\n", curCost.d, curCost.infs);
  139.     curCost += mcf();
  140.     LOG("%lld %lld\n", curCost.d, curCost.infs);
  141.     if (curCost.infs)
  142.         puts("-1");
  143.     else
  144.         printf("%lld\n", curCost.d);
  145.     return 0;
  146. }
  147.  
  148. Num mcf() {
  149.     Num cost = 0;
  150.     while (spth()) {
  151.         LOG("%lld %lld\n", dist[T].d, dist[T].infs);
  152.         if (!(dist[T] < 0))
  153.             break;
  154.         int flow = numeric_limits<int>::max();
  155.         int u = T;
  156.         while (u != S) {
  157.             flow = min(flow, pth[u]->rev->w);
  158.             u = pth[u]->v;
  159.         }
  160.         cost += dist[T] * flow;
  161.         u = T;
  162.         while (u != S) {
  163.             pth[u]->w += flow;
  164.             pth[u]->rev->w -= flow;
  165.             u = pth[u]->v;
  166.         }
  167.     }
  168.     return cost;
  169. }
  170.  
  171. bool spth() {
  172.     queue<int> q;
  173.     memset(pth, 0, sizeof(pth));
  174.     memset(inq, 0, sizeof(inq));
  175.     inq[S] = true;
  176.     dist[S] = 0;
  177.     q.push(S);
  178.     while (!q.empty()) {
  179.         int u = q.front();
  180.         q.pop();
  181.         LOG("BFS %d %lld %lld\n", u, dist[u].d, dist[u].infs);
  182.         inq[u] = false;
  183.         for (Edge* p = g[u]; p; p = p->next)
  184.             if (p->w && p->v != S && (!pth[p->v] || dist[u] + p->c < dist[p->v])) {
  185.                 dist[p->v] = dist[u] + p->c;
  186.                 pth[p->v] = p->rev;
  187.                 if (!inq[p->v]) {
  188.                     q.push(p->v);
  189.                     inq[p->v] = true;
  190.                 }
  191.             }
  192.     }
  193.     return pth[T];
  194. }
  195.  
  196. void link(int u, int v, int w, const Num& c) {
  197.     LOG("LINK %d %d %d %lld + %lldINF\n", u, v, w, c.d, c.infs);
  198.     Edge *p = addEdge(u, v, w, c),
  199.             *q = addEdge(v, u, 0, c * -1);
  200.     p->rev = q;
  201.     q->rev = p;
  202. }
  203.  
  204. Edge* addEdge(int u, int v, int w, const Num& c) {
  205.     static Edge pool[V * V * 4];
  206.     static Edge* p = pool;
  207.     p->v = v;
  208.     p->w = w;
  209.     p->c = c;
  210.     p->next = g[u];
  211.     g[u] = p;
  212.     return p++;
  213. }
Advertisement
Add Comment
Please, Sign In to add comment