Cod sursa(job #1738312)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 6 august 2016 13:58:43
Problema Algola Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.2 kb
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

constexpr int maxN = 50;
constexpr int maxM = 300;
constexpr int maxTime = 128;
constexpr int setSource = 0;
constexpr int setSink = 1;
constexpr int NIL = -1;

pair <pair <int, int>, int> E[maxM];
int ini_cap[maxN];

struct MaxFlow {
  struct Edge {
    int v, cap;
    int next;
  } G[maxM * maxTime];

  int head[maxN * maxTime];

  MaxFlow() {
    memset(head, NIL, 4 * maxN * maxTime);
  }

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

  void insertEdge( const int u, const int v, const int cap ) {
    addEdge(u, v, cap);
    addEdge(v, u, 0);
  }

  int dist[maxN * maxTime];
  int Q[maxN * maxTime];

  bool BFS() {
    memset(dist, 0, 4 * maxN * maxTime);
    int qHead = 0, qTail = 1;
    
    Q[0] = setSource;
    dist[setSource] = 1;

    while (qHead != qTail) {
      const int node = Q[qHead++];
      for (int i = head[node]; i != NIL; i = G[i].next) {
        const int to = G[i].v;
        if (G[i].cap > 0 && !dist[to]) {
          dist[to] = dist[node] + 1;
          Q[qTail++] = to;
        }
      }
    }
    return dist[setSink];
  }

  int to[maxN * maxTime];

  int DFS( const int node, const int flow ) {
    if (node == setSink || !flow)
      return flow;

    for (; to[node] != NIL; to[node] = G[to[node]].next)
      if (dist[G[to[node]].v] == dist[node] + 1) {
        const int push_flow = (flow < G[to[node]].cap) ? flow : G[to[node]].cap;
        const int pushed = DFS(G[to[node]].v, push_flow);
        if (pushed) {
          G[to[node]].cap -= pushed;
          G[to[node] ^ 1].cap += pushed;
          return pushed;
        }
      }
    return 0;
  }

  int maxFlow() {
    int flow = 0;
    while (BFS()) {
      memmove(to, head, 4 * maxN * maxTime);
      int pushed;
      do {
        pushed = DFS(setSource, maxN);
        flow += pushed;
      } while (pushed);
    }
    return flow;
  }

} Dinic;

int n, m;

int pushTime( int &delta ) {
  for (int i = 0; i < n; i++) // raman pe aceeasi pozitie
    Dinic.insertEdge(delta - n + i, delta + i, maxN);

  for (int i = 0; i < m; i++) { // se muta in vecin
    Dinic.insertEdge(delta - n + E[i].first.first, delta + E[i].first.second, E[i].second);
    Dinic.insertEdge(delta - n + E[i].first.second, delta + E[i].first.first, E[i].second);
  }

  Dinic.insertEdge(delta, setSink, maxN);

  delta += n;

  return Dinic.maxFlow();
}

int main() {
  freopen("algola.in", "r", stdin);
  freopen("algola.out", "w", stdout);

  int need_flow = 0;
  scanf("%d%d", &n, &m);
  for (int i = 0; i < n; i++) {
    scanf("%d", ini_cap + i);
    need_flow += ini_cap[i];
  }
  
  if (*ini_cap == need_flow) {
    puts("0");
    return 0;
  }

  for (int i = 0; i < m; i++) {
    scanf("%d%d%d", &E[i].first.first, &E[i].first.second, &E[i].second);
    E[i].first.first--;
    E[i].first.second--;
  }

  int delta = 2;
  for (int i = 0; i < n; i++)
    Dinic.insertEdge(setSource, delta + i, ini_cap[i]);

  Dinic.insertEdge(delta, setSink, maxN);
  delta += n;

  int theta = 1;
  while (need_flow -= pushTime(delta))
    theta++;

  printf("%d\n", theta);

  return 0;
}