Cod sursa(job #1688873)

Utilizator BugirosRobert Bugiros Data 13 aprilie 2016 19:36:08
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.13 kb
#include <fstream>
#include <vector>
using namespace std;

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

int n,m;

const int MAXN = 710;
const int INF = 1 << 30;

vector<int> vecini[MAXN], cost[MAXN];

int idmuchie[MAXN][MAXN];//idmuchie[i][j] - indicele muchiei intre i si j
int capacitate[MAXN][MAXN];//Atentie! Trebuie cu matrice de adiacenta deoarece avem nevoie de capacitatea intre doua noduri in O(1)
int flux[MAXN][MAXN];//Atentie! Trebuie cu matrice de adiacenta deoarece avem nevoie de fluxul intre doua noduri in O(1)
int sursa,destinatie;

void citire()
{
    int e;
    in >> n >> m >> e;
    for (int i = 1;i <= e;++i)
    {
        int x,y,c;
        in >> x >> y >> c;
        ++x;//       muchiile x si y
        y += n + 1;//sunt iduri din doua multimi, deci le concatenam

        vecini[x].push_back(y);
        cost[x].push_back(c);
        //construim graful rezidual, deci de la y la x
        vecini[y].push_back(x);
        cost[y].push_back(-c);
        idmuchie[x][y] = i;
        capacitate[x][y] = 1;
    }
}

void construire_graf_flux()
//construim un graf pe care putem aplica fluxul maxim de cost minim
{
    sursa = 1;
    destinatie = n + m + 2;
    for (int i = 2;i <= n + 1;++i)
    //legam sursa de nodurile din prima multime
    {
        vecini[sursa].push_back(i);
        cost[sursa].push_back(0);
        vecini[i].push_back(sursa);
        cost[i].push_back(0);
        capacitate[sursa][i] = 1;
    }

    for (int i = n + 2;i <= n + m + 1;++i)
    //legam sursa de nodurile din prima multime
    {
        vecini[i].push_back(destinatie);
        cost[i].push_back(0);
        vecini[destinatie].push_back(i);
        cost[destinatie].push_back(0);
        capacitate[i][destinatie] = 1;
    }
}

int bellmanford()
//intoarce costul drumului de ameliorare sau 0 daca nu mai exista drum de ameliorare
{
    int d[MAXN];
    int tata[MAXN];
    bool in_coada[MAXN];
    int coada[MAXN * MAXN] = {0};
    for (int i = sursa;i <= destinatie;++i)
    {
        d[i] = INF;
        tata[i] = -1;
        in_coada[i] = false;
    }
    d[sursa] = 0;
    int p = 1,q = 1;
    coada[1] = sursa;
    in_coada[sursa] = true;
    while(p <= q)
    {
        int nod = coada[p];
        for (unsigned int i = 0;i < vecini[nod].size();++i)
        {
            int vecin = vecini[nod][i];
            if (vecin == destinatie)
                vecin = destinatie;
            int cst = cost[nod][i];
            if (capacitate[nod][vecin] > flux[nod][vecin] && d[nod] + cst < d[vecin])
            {
                d[vecin] = d[nod] + cst;
                tata[vecin] = nod;
                if (!in_coada[vecin])
                {
                    coada[++q] = vecin;
                    in_coada[vecin] = true;
                }
            }
        }
        ++p;
        in_coada[nod] = false;
    }

    if (d[destinatie] == INF)
        return 0;
    int influx = INF;
    for (int i = destinatie;i != sursa;i = tata[i])
    {
        int x = capacitate[tata[i]][i] - flux[tata[i]][i];
        if (x < influx)
            influx = x;
    }
    for (int i = destinatie;i != sursa;i = tata[i])
    {
        flux[tata[i]][i] += influx;
        flux[i][tata[i]] -= influx;
    }
    return influx * d[destinatie];
}


int nr_muchii_rasp, cost_minim;

void afisare()
{
    for (int i = 2;i <= n + 1;++i)
        for (int j = n + 2;j <= n + m + 2;++j)
            if (capacitate[i][j] != 0 && flux[i][j] != 0)
            {
                ++nr_muchii_rasp;
                break;
            }
    out << nr_muchii_rasp << ' ' << cost_minim << '\n';
    for (int i = 2;i <= n + 1;++i)
        for (int j = n + 2;j <= n + m + 2;++j)
            if (capacitate[i][j] != 0 && flux[i][j] != 0)
            {
                out << idmuchie[i][j] << ' ';
                break;
            }
    out << '\n';
}

int main()
{
    citire();
    construire_graf_flux();
    int cost_pred = -1;
    while(cost_minim != cost_pred)
    {
        cost_pred = cost_minim;
        cost_minim += bellmanford();
    }
    afisare();
    return 0;
}