Cod sursa(job #1710219)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 28 mai 2016 17:50:11
Problema Tribut Scor 100
Compilator cpp Status done
Runda Arhiva ICPC Marime 2.29 kb
#include <bits/stdc++.h>

using namespace std;

constexpr int MAX_N = 100;
constexpr int NIL = -1;

struct Edge {
  int v;
  int cap;
  int next;
} G[2 * MAX_N * (2 + MAX_N)];

int head[2 * MAX_N + 2];

int pos;

void addEdge(const int u, const int v,
             const int cap) {
  G[pos].v = v;
  G[pos].cap = cap;
  G[pos].next = head[u];
  head[u] = pos++;
}

int Q[2 * MAX_N + 2];
bool color[2 * MAX_N + 2];
int parent[2 * MAX_N + 2];
int pointer[2 * MAX_N + 2];

bool BFS(const int source, const int sink) {
  int qStart = 0, qEnd = 1;
  memset(color + 1, 0, sink);
  color[0] = 1;
  Q[0] = source;
  while (qStart != qEnd) {
    const int u = Q[qStart++];
    for (int i = head[u]; i != NIL; i = G[i].next) {
      const int v = G[i].v;
      if (G[i].cap && !color[v]) {
        color[v] = 1;
        Q[qEnd++] = v;
        parent[v] = u;
        pointer[v] = i;
      }
    }
  }
  return color[sink];
}

int main() {
  ifstream fin("tribut.in");
  ofstream fout("tribut.out");
  fin.tie(0);
  ios_base::sync_with_stdio(0);

  int numTests; fin >> numTests;

  while (numTests--) {
    int n, m; fin >> n >> m;
    memset(head, NIL, 4 * (1 + n + m + 1));
    pos = 0;
    for (int i = 0; i < n; i += 1) {
      int budget; fin >> budget;
      addEdge(0, i + 1, budget);
      addEdge(i + 1, 0, 0);
    }
    for (int i = 0; i < m; i += 1) {
      int budget_union, adjSolars; fin >> adjSolars >> budget_union;
      if (budget_union) {
        addEdge(i + n + 1, n + m + 1, budget_union);
        addEdge(n + m + 1, i + n + 1, 0);
      }
      for (int j = 0; j < adjSolars; j += 1) {
        int solar; fin >> solar;
        if (budget_union) {
          addEdge(solar, i + n + 1, G[(solar - 1) << 1].cap);
          addEdge(i + n + 1, solar, 0);
        }
      }
    }
    int ret = 0;
    while (BFS(0, n + m + 1)) {
      int fmin = numeric_limits <int> :: max();
      for (int i = n + m + 1; i; i = parent[i]) {
        if (fmin > G[pointer[i]].cap)
          fmin = G[pointer[i]].cap;
      }
      for (int i = n + m + 1; i; i = parent[i]) {
        G[pointer[i]].cap -= fmin;
        G[pointer[i] ^ 1].cap += fmin;
      }
      ret += fmin;
    }
    fout << ret << '\n';
  }
  fin.close();
  fout.close();

  return 0;
}