Cod sursa(job #2010588)

Utilizator GoogalAbabei Daniel Googal Data 13 august 2017 17:55:37
Problema Cuplaj maxim de cost minim Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 3.85 kb
#include <algorithm>
#include <iostream>
#include <fstream>
#include <climits>
#include <cassert>
#include <bitset>
#include <vector>
#include <queue>

using namespace std;

ifstream in("cmcm.in");
ofstream out("cmcm.out");

const int NMAX = 2 * (300 + 1);

struct Edge{
  int to;
  int rev;
  int flow;
  int cap;
  int cost;
  int ind;
};

struct Node{
  int node;
  int d;

  bool operator> (Node other) const{
    return d > other.d;
  }
};

int n, m, e, src, dest;
int dist[1 + NMAX], distdij[1 + NMAX];
bitset<1 + NMAX> vis;
int prevnode[1 + NMAX], prevedge[1 + NMAX], pushflow[1 + NMAX];

vector < Edge > g[1 + NMAX];

void addedge(int from, int to, int cost, int ind){
  Edge direct  = {to, g[to].size(), 0, 1, cost, ind};
  Edge inverse = {from, g[from].size(), 0, 0, -cost, -1};

  g[from].push_back(direct);
  g[to].push_back(inverse);
}

void bellmanford(){
  queue < int > q;
  fill(dist, dist + dest + 1, INT_MAX);
  dist[src] = 0;
  q.push(src);

  while(!q.empty()){
    int from = q.front();
    vis[from] = 0;
    q.pop();

    for(int i = 0; i < g[from].size(); i++){
      Edge &e = g[from][i];
      if(e.flow < e.cap){
        int to = e.to;
        int newdist = dist[from] + e.cost;
        if(newdist < dist[to]){
          dist[to] = newdist;
          if(vis[to] == 0){
            q.push(to);
            vis[to] = 1;
          }
        }
      }
    }
  }
}

void dijkstra(){
  vis = 0;
  distdij[src] = 0;
  pushflow[src] = INT_MAX;

  priority_queue<Node, vector <Node>, greater<Node> > pq;
  pq.push({src, distdij[src]});

  while(!pq.empty()){
    int from = pq.top().node;
    pq.pop();

    if(vis[from] == 0){
      vis[from] = 1;
      for(int i = 0; i < g[from].size(); i++){
        Edge &e = g[from][i];
        if(vis[e.to] == 0){
          int to = e.to;
          if(e.flow < e.cap){
            int newdistdij = distdij[from] + e.cost + dist[from] - dist[to];
            if(newdistdij < distdij[to]){
              distdij[to] = newdistdij;
              prevnode[to] = from;
              prevedge[to] = i;
              pushflow[to] = min(pushflow[from], e.cap - e.flow);
              pq.push({to, distdij[to]});
            }
          }
        }
      }
    }
  }
}

void mincostflow(int &flow, int &flowcost){
  bellmanford();
  //cout << "BF\n";

  flow = flowcost = 0;
  while(distdij[dest] < INT_MAX){
    fill(distdij, distdij + dest + 1, INT_MAX);
    dijkstra();
    //cout << "DJ\n";
    if(distdij[dest] < INT_MAX){
      for(int i = 1; i <= n; i++){
        dist[i] += distdij[i];
      }

      int deltaflow = pushflow[dest];
      flow += deltaflow;

      for(int to = dest; to != src; to = prevnode[to]){
        Edge &e = g[prevnode[to]][prevedge[to]];
        e.flow += deltaflow;
        g[to][e.rev].flow -= deltaflow;
        flowcost += deltaflow * e.cost;
      }
    }
  }
}

int main()
{
  in >> n >> m >> e;
  src = 0;
  dest = n + m + 1;
  for(int i = 1; i <= e; i++){
    int from, to, cost;
    in >> from >> to >> cost;
    to += n;
    addedge(from, to, cost, i);
  }

  for(int i = 1; i <= n; i++){
    addedge(src, i, 0, -1);
  }

  for(int i = n + 1; i <= n + m; i++){
    addedge(i, dest, 0, -1);
  }

  int flow, flowcost;
  mincostflow(flow, flowcost);
  //assert(0 < flowcost);
  //assert(flow == n);
  out << flow << ' ' << flowcost << '\n';

  for(int i = 1; i < dest; i++){
    for(int j = 0; j < g[i].size(); j++){
      Edge &e = g[i][j];
      /*
      cout << i << ' ';
      cout << e.to << ' ';
      cout << e.flow << ' ';
      cout << e.cap << ' ';
      cout << e.cost << ' ';
      cout << e.ind << ' ';
      cout << '\n';
      */
      if(e.ind != -1 && e.flow == e.cap)
        out << e.ind << ' ';
    }
  }

  in.close();
  out.close();
  return 0;
}