Cod sursa(job #2079324)

Utilizator DruffbaumPopescu Vlad Druffbaum Data 30 noiembrie 2017 23:32:59
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.12 kb
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>

const int MAXN = 6e2;
const int INF = 0x3f3f3f3f;

std::vector <int> g[MAXN + 2];
int flow[MAXN + 2][MAXN + 2], cap[MAXN + 2][MAXN + 2],
    cost[MAXN + 2][MAXN + 2], fath[MAXN + 2],
    dist[MAXN + 2], edge[MAXN + 1][MAXN + 1];
bool inq[MAXN + 2];
std::queue <int> q;

static inline int min(int a, int b) {
  return a > b ? b : a;
}

bool bellman(int s, int d) {
  int u;
  memset(dist, INF, sizeof(dist));
  dist[s] = 0;
  q.push(s);
  while (!q.empty()) {
    u = q.front();
    q.pop();
    inq[u] = 0;
    for (auto v: g[u]) {
      if (flow[u][v] < cap[u][v] && dist[v] > dist[u] + cost[u][v]) {
        dist[v] = dist[u] + cost[u][v];
        fath[v] = u;
        if (!inq[v]) {
          inq[v] = 1;
          q.push(v);
        }
      }
    }
  }
  return (dist[d] < INF);
}

int main() {
  int n, m, e, u, v, c, fl, maxfl, mincost;
  FILE *f = fopen("cmcm.in", "r");
  fscanf(f, "%d%d%d", &n, &m, &e);
  for (int i = 0; i < e; ++i) {
    fscanf(f, "%d%d%d", &u, &v, &c);
    v += n;
    g[u].push_back(v);
    g[v].push_back(u);
    edge[u][v] = i + 1;
    cost[u][v] = c;
    cost[v][u] =-c;
    cap[u][v] = 1;
  }
  fclose(f);
  u = 0;
  for (v = 1; v <= n; ++v) {
    g[u].push_back(v); 
    g[v].push_back(u);
    cap[u][v] = 1;
  }
  u = n + m + 1;
  for (v = n + 1; v <= n + m; ++v) {
    g[u].push_back(v);
    g[v].push_back(u);
    cap[v][u] = 1;
  }
  maxfl = mincost = 0;
  while (bellman(0, n + m + 1)) {
    fl = INF;
    u = n + m + 1;
    while (u > 0) {
      fl = min(fl, cap[fath[u]][u] - flow[fath[u]][u]);
      u = fath[u];
    }
    u = n + m + 1;
    while (u > 0) {
      flow[fath[u]][u] += fl;
      flow[u][fath[u]] -= fl;
      u = fath[u];
    }
    maxfl += fl;
    mincost += fl * dist[n + m + 1];
  }
  f = fopen("cmcm.out", "w");
  fprintf(f, "%d %d\n", maxfl, mincost);
  for (u = 1; u <= n; ++u) {
    for (v = n + 1; v <= n + m; ++v) {
      if (flow[u][v] && cap[u][v]) {
        fprintf(f, "%d ", edge[u][v]);
      }
    }
  }
  fclose(f);
  return 0;
}