Cod sursa(job #3258471)

Utilizator razviii237Uzum Razvan razviii237 Data 22 noiembrie 2024 16:39:31
Problema Cuplaj maxim de cost minim Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.33 kb
#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
#include <queue>

using namespace std;

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

const int maxn = 302, inf = 0x3f3f3f3f;

int n, m, s, d;
int cap[maxn][maxn], cst[maxn][maxn];
vector<int> v[maxn];
queue<int> q;
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > pq;
vector<pair<int, int> > muchii;
int originalDistance[maxn], dist[maxn], realDistance[maxn], p[maxn], indice[maxn][maxn];
bool inQ[maxn];
int finalCost, finalFlow;

void bellmanford() {
    memset(originalDistance, inf, sizeof(originalDistance));
    originalDistance[s] = 0;
    q.push(s);
    inQ[s] = true;
    while(!q.empty()) {
        int x = q.front();
        inQ[x] = false;
        for(auto u : v[x]) {
            if(cap[x][u]) {
                if(originalDistance[x] + cst[x][u] < originalDistance[u]) {
                    originalDistance[u] = originalDistance[x] + cst[x][u];
                    if(inQ[u] == false) {
                        inQ[u] = true;
                        q.push(u);
                    }
                }
            }
        }

        q.pop();
    }
}

bool dijkstra() {
//    cout << "entered dijkstra\n";
    memset(dist, inf, sizeof(dist));
    dist[s] = 0; realDistance[s] = 0;
    pq.push({dist[s], s});

    while(!pq.empty()) {
        int currCost = pq.top().first;
        int currNode = pq.top().second;
        pq.pop();
        if(dist[currNode] != currCost) // eu pun acelasi nod de mai multe ori in pq daca e nevoie
            continue; // dar il iau doar atunci cand distanta e cea mai mica
        for(auto u : v[currNode]) {
            if(cap[currNode][u]) {
                int newDist = dist[currNode] + cst[currNode][u] + originalDistance[currNode] - originalDistance[u];
//                cout << "cost from " << currNode << " to " << u << " is " << cst[currNode][u] + originalDistance[currNode] - originalDistance[u] << '\n';
                if(newDist < dist[u]) {
                    dist[u] = newDist;
                    realDistance[u] = realDistance[currNode] + cst[currNode][u];
                    p[u] = currNode;
                    pq.push({dist[u], u});
                }
            }
        }
    }

//    cout << "old distance: ";
//    for(int i = 1; i <= n; i ++) {
//        cout << originalDistance[i] << ' ';
//    }
//    cout << "\nreal distance: ";
//    for(int i = 1; i <= n; i ++) {
//        cout << realDistance[i] << ' ';
//    }
//    cout << '\n';
    memcpy(originalDistance, realDistance, sizeof(originalDistance));
    if(dist[d] == inf) // daca nu a facut drum pana la destinatie, nu s-a mai imbunatatit,
        return false; // deci ne oprim

    int minim = inf, curCst = 0;
    for(int i = d; i != s; i = p[i]) {
        minim = min(minim, cap[p[i]][i]);
        curCst += cst[p[i]][i];
    }
    finalFlow += minim;
    finalCost += curCst * minim; // sau minim * realDistance[d]
    for(int i = d; i != s; i = p[i]) {
        cap[p[i]][i] -= minim;
        cap[i][p[i]] += minim;
    }
    return true;
}

int main()
{
    int x, y, e;
//    fin >> n >> m >> s >> d;
//
//    while(m --) {
//        fin >> x >> y;
//        fin >> cap[x][y] >> cst[x][y];
//        cst[y][x] = -cst[x][y];
//        v[x].push_back(y);
//        v[y].push_back(x);
//    }
    fin >> n >> m;
    fin >> e;
//    int i = 1;
    while(e --) {
        fin >> x >> y;
        y += n;
        muchii.push_back({x, y});
//        indice[x][y] = i;
        fin >> cst[x][y];
        cst[y][x] = -cst[x][y];
        cap[x][y] = 1;
        v[x].push_back(y);
        v[y].push_back(x);
//        i ++;
    }
    // n+m+1 -> sursa
    // n+m+1 -> destinatia
    s = n + m + 1;
    d = n + m + 2;
    for(int i = 1; i <= n; i ++) {
        v[s].push_back(i);
        v[i].push_back(s);
        cst[i][s] = 0;
        cst[s][i] = 0;
        cap[s][i] = 1;
    }
    for(int i = n + 1; i <= n + m; i ++) {
        v[i].push_back(d);
        v[d].push_back(i);
        cst[i][d] = 0;
        cst[d][i] = 0;
        cap[i][d] = 1;
    }

    n = n + m + 2;

    bellmanford();
    while(dijkstra());

    fout << finalFlow << ' ' << finalCost << '\n';
    int i = 1;
    for(auto muchie : muchii) {
        if(cap[muchie.first][muchie.second] == 0)
            fout << i << ' ';
        i ++;
    }
    fout << '\n';

    fin.close();
    fout.close();
    return 0;
}