Cod sursa(job #2599730)

Utilizator SoranaAureliaCatrina Sorana SoranaAurelia Data 11 aprilie 2020 18:31:29
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.97 kb
#include <fstream>
#include <queue>
#include <vector>
#include <map>
#include <cstring>
#include <bitset>

#define oo 0x3f3f3f3f
#define NMAX 305
#define MMAX 305
#define TMAX 605
#define EMAX 50005
using namespace std;

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

typedef pair<int, int> pii;

int n, m, e; // cardinalul primei mulrimi, cardinalul celei de a doua multime, numarul de muchii
int flow[TMAX][TMAX], cap[TMAX][TMAX];
int dmin[TMAX]; // dist[i] = distanta de la sursa la i -> bellman ford
int dmindij[TMAX]; // distdij[i] = distanta de la sursa la i -> dijkstra !!niciun nr negativ
int tati[TMAX]; // pt a recrea drumul de cost minim
int dnealterat[TMAX]; // drum fara a lua in calcul artificiul pt pozitiv
int s, d; //sursa, destinatia
int x, y, c;
int muchii; //nr muchii rezultat
int ans=0;

struct muchie{
    int y;
    int cost;
    bool operator<(const muchie &other) const{
        if(cost!=other.cost)
            return cost>other.cost;
        return y<other.y;
    }
};
vector<muchie> graph[TMAX];
map<pii, int> edges;

void citire(){
    f>>n>>m>>e;
    for(int t=1; t<=e; t++){
        f>>x>>y>>c;
        y+=n;
        edges[{x, y}] = t;

        graph[x].push_back({y, c});
        graph[y].push_back({x, -c});

        cap[x][y] = 1;
        cap[y][x] = 0;

    }
}

void adaug_sursa_dest(){
    s=0;
    d=n+m+1;
    for(int i=1; i<=n; i++){
        graph[0].push_back({i, 0});
        graph[i].push_back({0, 0});
        cap[0][i] = 1;
        cap[i][0] = 0;
    }
    for(int i=n+1; i<=n+m; i++){
        graph[i].push_back({d, 0});
        graph[d].push_back({i, 0});
        cap[i][d] = 1;
        cap[d][i] = 0;
    }
}

void bellman(){
    bitset<TMAX> viz;
    viz.reset();
    memset(dmin, 0x3f, sizeof(dmin));

    queue<int> Q;
    Q.push(s);
    dmin[s] = 0;
    viz[s] = true;
    while(!Q.empty()){
        int nod = Q.front();
        Q.pop();
        viz[nod] = false;
        for(auto &v:graph[nod])
            if(cap[nod][v.y] != flow[nod][v.y] && dmin[nod] + v.cost<dmin[v.y]){
                dmin[v.y] = dmin[nod] + v.cost;
                if(viz[v.y] == false)
                    Q.push(v.y);
                viz[v.y] = true;
            }
    }
}

int costNou(int cost, int nod1, int nod2){
    return cost + dmin[nod1] - dmin[nod2];
}

bool dijkstra(){
    bitset<TMAX> viz;
    viz.reset();
    memset(dmindij, 0x3f, sizeof(dmindij));
    memset(dnealterat, 0x3f, sizeof(dnealterat));

    priority_queue<muchie>Q;
    dmindij[s] = 0;
    dmin[s] = 0;
    dnealterat[s] = 0;
    Q.push({s, 0});

    while(!Q.empty()){
        int nod = Q.top().y;
        Q.pop();
        if(viz[nod] == true)
            continue;
        viz[nod] = false;
        for(auto &v:graph[nod])
            if(flow[nod][v.y]!=cap[nod][v.y] && dmindij[nod] + costNou(v.cost, nod, v.y)<dmindij[v.y]){
                dmindij[v.y] = dmindij[nod] + costNou(v.cost, nod, v.y);
                dnealterat[v.y] = dnealterat[nod] + v.cost;
                tati[v.y] = nod;
                Q.push({v.y, dmindij[v.y]});
            }
    }
    return dmindij[d]!=oo;
}

void solve(){
    while(dijkstra()){
        int maxFlow = oo;
        for(int i=d; i!=s; i=tati[i])
            maxFlow = min(maxFlow, cap[tati[i]][i] - flow[tati[i]][i]);
        if(maxFlow == 0)
            continue;
        ans += maxFlow*dnealterat[d];
        for(int i=d; i!=s; i=tati[i]){
            flow[tati[i]][i] += maxFlow;
            flow[i][tati[i]] -= maxFlow;
        }
        for(int i=1; i<=n+m+1; i++)
            dmin[i] = dnealterat[i];
        muchii++;
    }

}

void afisare(){
    g<<muchii<<" "<<ans<<'\n';
    for(int i=1; i<=n; i++)
        for(int j=n+1; j<=n+m; j++)
            if(flow[i][j] == 1){
                g<<edges[{i, j}]<<" ";
            }
}
int main()
{
    citire();
    adaug_sursa_dest();
    bellman();
    solve();
    afisare();
    return 0;
}