Cod sursa(job #2020560)

Utilizator EuAlexOtaku Hikikomori EuAlex Data 10 septembrie 2017 18:48:02
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.08 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

const int inf = 1000000000;
const int nmax = 303;

int n;
int w[1 + nmax][1 + nmax];
int etu[1 + nmax], etv[1 + nmax];
int index[1 + nmax][1 + nmax];
int visu[1 + nmax], visv[1 + nmax];
int match[1 + nmax];

int dfs(int u) {

  visu[u] = 1;
  for(int v = 1; v <= n; ++ v) {
    int exces = etu[u] + etv[v] - w[u][v];
    if(visv[v] == 0 && exces == 0) {
      visv[v] = 1;
      if(match[v] == 0 || dfs(match[v]) == 1) {
        match[v] = u;
        return 1;
      }
    }
  }
  return 0;
}

void hungarian() {

  for(int i = 1; i <= n; ++ i) {
    etu[i] = w[i][1];
    for(int j = 2; j <= n; ++ j) {
      etu[i] = max(etu[i], w[i][j]);
    }
  }

  for(int i = 1; i <= n; i++) {

    while(dfs(i) == 0) {

      int epsilon = inf;
      for(int j = 1; j <= n; ++ j) {
        if(visu[j] == 1)
          for(int k = 1; k <= n; ++ k) {
            if(visv[k] == 0)
              if(etu[j] + etv[k] - w[j][k] < epsilon)
                epsilon  = etu[j] + etv[k] - w[j][k];
          }
      }

      for(int j = 1; j <= n; ++ j) {
        if(visu[j] == 1) {
          etu[j] -= epsilon;
          visu[j] = 0;
        }
        if(visv[j] == 1) {
          etv[j] += epsilon;
          visv[j] = 0;
        }
      }
    }
  }
}

int main() {
    ifstream in("cmcm.in");
    ofstream out("cmcm.out");
  int na, nb, m;
  in >> na >> nb >> m;

  n = max(na, nb);

  for(int i = 1; i <= n; ++ i) {
    for(int j = 1; j <= n; ++ j) {
      w[i][j] = -inf;
    }
  }
  for(int i = 1; i <= m; ++ i) {
    int x, y, z;
    in >> x >> y >> z;
    w[x][y] = -z;
    index[x][y] = i;
  }
  hungarian();

  int answer = 0;
  vector<int> edges;
  for(int i = 1; i <= n; ++ i) {
    if(w[match[i]][i] != -inf) {
      edges.push_back(index[match[i]][i]);
      answer += w[match[i]][i];
    }
  }
  out << edges.size() << " " << -answer << '\n';
  for(int i = 0; i < edges.size(); ++ i) {
    out << edges[i] << " ";
 }
  return 0;
}