Cod sursa(job #2764085)

Utilizator DragosC1Dragos DragosC1 Data 19 iulie 2021 13:40:08
Problema Cuplaj maxim de cost minim Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.45 kb
#include <fstream>
#include <vector>
#include <queue>
#include <iostream>
using namespace std;

int n, m, u, nodfinal;
int armata[10001];

vector<int> a[10001];

int sol;

void read() {
    int i, x, y;
    ifstream f("atac2.in");
    f >> n >> m >> u >> nodfinal;
    for (i = 1; i <= u; i++) 
        f >> armata[i];
    for (i = 1; i <= m; i++) {
        f >> x >> y;
        a[x].emplace_back(y);
        a[y].emplace_back(x);
    }
    f.close();
}

int d[10001];
int viz[10001];

queue<int> Q;
void bfs(int x) {
    int i, fiu;
    for (i = 1; i <= n; i++) {
        d[i] = -1;
        viz[i] = 0;
    }
    viz[x] = 1;
    d[x] = 0;
    Q.push(x);
    while (!Q.empty()) {
        x = Q.front();
        Q.pop();
        for (i = 0; i < a[x].size(); i++)
            if (!viz[a[x][i]]) {
                fiu = a[x][i];
                d[fiu] = d[x] + 1;
                viz[fiu] = 1;
                Q.push(fiu);
            }
    }
}

vector<pair<int, int>> bipartit[151];
int Ma, Mb;
int C[151][151], F[151][151], t[151];
int dest;

void makeGraph() {
    int i;
    dest = Ma + Mb + 2;
    for (i = 2; i <= u + 1; i++) {
        bipartit[1].push_back({i, 0});
        bipartit[i].push_back({1, 0});
        C[1][i] = 1;
    }
    for (i = u + 2; i <= Ma + Mb + 1; i++) {
        bipartit[i].push_back({dest, 0});
        bipartit[dest].push_back({i, 0});
        C[i][dest] = 1;
    }
}

const int Inf = 1e9;

pair<int, int> bellmanford() {
    int i, x;
    for (i = 1; i <= dest; i++) {
        d[i] = Inf;
        t[i] = -1;
        viz[i] = 0;
    }

    Q.push(1);
    d[1] = 0;
    viz[1] = 1;

    while (!Q.empty()) {
        x = Q.front();
        Q.pop();
        viz[x] = 0;
        for (i = 0; i < bipartit[x].size(); i++) 
            if (F[x][bipartit[x][i].first] != C[x][bipartit[x][i].first] && d[x] + bipartit[x][i].second < d[bipartit[x][i].first]) {
                d[bipartit[x][i].first] = d[x] + bipartit[x][i].second;
                t[bipartit[x][i].first] = x;
                if (!viz[bipartit[x][i].first]) {
                    viz[bipartit[x][i].first] = 1;
                    Q.push(bipartit[x][i].first);
                }
            }
        }
    if (d[dest] < Inf) {
        int flux = Inf;
        int nod = dest;
        while (nod != 1) {
            flux = min(flux, C[t[nod]][nod] - F[t[nod]][nod]);
            nod = t[nod];
        }
        nod = dest;
        while (nod != 1) {
            F[t[nod]][nod] += flux;
            F[nod][t[nod]] -= flux;
            nod = t[nod];
        }
        return {flux, d[dest]};
    }
    return {0, 0};
}

void solve() {
    int i, j, x, y;
    Ma = u, Mb = a[nodfinal].size();
    for (i = 1; i <= u; i++) {
        bfs(armata[i]);
        for (j = 0; j < a[nodfinal].size(); j++) {
            x = i + 1, y = j + 2 + u;
            if (d[a[nodfinal][j]] != -1) {
                bipartit[x].push_back({y, d[a[nodfinal][j]]});
                bipartit[y].push_back({x, -d[a[nodfinal][j]]});
                C[x][y] = 1;
            }
        }
    }
    makeGraph();

    pair<int, int> rez;
    int improve = 1;
    while (improve) {
        rez = bellmanford();
        improve = rez.first;
        sol = sol + rez.second;
    }
}

void output() {
    ofstream g("atac2.out");
    g << sol;
    g.close();
}

int main() {
    read();
    solve();
    output();
    return 0;
}