Cod sursa(job #2944659)

Utilizator iraresmihaiiordache rares mihai iraresmihai Data 22 noiembrie 2022 20:09:04
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.32 kb
#include <iostream>
#include <vector>
#include <queue>

#define MAXN 350
#define MAXDIST 10000
#define INF 1000000000
using namespace std;

struct node{
  bool visited, isInQ;
  int parent;
  vector <int> neighbours;
};

struct edgePq{
  int cost, b;
};

int cost[MAXN][MAXN];
int cap[MAXN][MAXN];
int dist[MAXN];
node graph[MAXN];
queue <int> q;
priority_queue <edgePq> pq;
int virtualDist[MAXN];
int realDist[MAXN];

bool operator<(edgePq a, edgePq b) {
  return a.cost > b.cost;
}

void addEdge(int a, int b, int costs, int capacity) {
  graph[a].neighbours.push_back(b);
  graph[b].neighbours.push_back(a);

  cap[a][b] = capacity;
  cost[a][b] = costs;
  cost[b][a] = -costs;
}

bool bf(int startPos, int n, int destination) {
  int i, pos;

  for ( i = 0; i < n; i++ ) {
    dist[i] = INF;
  }

  dist[startPos] = 1;
  q.push(startPos);
  graph[startPos].isInQ = true;

  while ( !q.empty() ) {
    pos = q.front();
    graph[pos].isInQ = false;
    q.pop();

    for ( int x : graph[pos].neighbours ) {
      if ( cap[pos][x] > 0 && dist[x] > dist[pos] + cost[pos][x] ) {
        dist[x] = dist[pos] + cost[pos][x];
        if ( !graph[x].isInQ ) {
          graph[x].isInQ = true;
          q.push(x);
        }
      }
    }
  }

  return dist[destination] != INF;
}

bool dijkstra(int startPos, int n, int sink) {
  int i;
  int pos;

  for ( i = 0; i < n; i++ ) {
    realDist[i] = dist[i];
    virtualDist[i] = INF;
    graph[i].visited = false;
  }

  pq.push({0, startPos});
  virtualDist[startPos] = 0;
  while ( !pq.empty() ) {
    pos = pq.top().b;
    pq.pop();

    if ( !graph[pos].visited ) {
      graph[pos].visited = true;
      for ( int x : graph[pos].neighbours ) {
         // printf("%d %d\n", virtualDist[x], virtualDist[pos] + cost[pos][x] + realDist[pos] - realDist[x]);
        if ( cap[pos][x] > 0 && virtualDist[x] > virtualDist[pos] + cost[pos][x] + realDist[pos] - realDist[x] ) {
          virtualDist[x] = virtualDist[pos] + cost[pos][x] + realDist[pos] - realDist[x];
          graph[x].parent = pos;
          dist[x] = dist[pos] + cost[pos][x];
          pq.push({virtualDist[x], x});
        }
      }
    }
  }

  return virtualDist[sink] != INF;
}

int main() {
  FILE *fin, *fout;
  fin = fopen("fmcm.in", "r");
  fout = fopen("fmcm.out", "w");

  int n, m, s, d, i, a, b, costs, capacity, totCost, nod, flow, costForWay;
  bool canReach;

  fscanf(fin, "%d%d%d%d", &n, &m, &s, &d);
  s--;
  d--;

  for ( i = 0; i < m; i++ ) {
    fscanf(fin, "%d%d%d%d", &a, &b, &capacity, &costs);
    a--;
    b--;

    addEdge(a, b, costs, capacity);
  }

  canReach = bf(s, n, d);

  totCost = 0;
  if ( canReach ) {
    while ( dijkstra(s, n, d) ) {
      nod = d;
      costForWay = 0;
      flow = INF;
      while ( nod != s ) {
        flow = min(flow, cap[graph[nod].parent][nod]);
        costForWay += cost[graph[nod].parent][nod];
        nod = graph[nod].parent;
      }

      totCost += costForWay * flow;

      nod = d;
      while ( nod != s ) {
        cap[graph[nod].parent][nod] -= flow;
        cap[nod][graph[nod].parent] += flow;
        nod = graph[nod].parent;
      }
      //printf("\n");
    }
  }

  fprintf(fout, "%d\n", totCost);

  fclose(fin);
  fclose(fout);

  return 0;
}