Cod sursa(job #2949631)

Utilizator Fantastic_Mantudor voicu Fantastic_Man Data 1 decembrie 2022 12:00:31
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.93 kb
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int nmax = 602;
const int oo = 1e9;

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

struct edge {
    int a; int b;
    int flux;
    int cost;
};

vector < edge > edges;
vector < int > adj[nmax + 1];

bool inQ[nmax + 1];

int dist[nmax + 1];
int real_dist[nmax + 1];
int fake_dist[nmax + 1];
bool vis[nmax + 1];
int p[nmax + 1];
int p_edge[nmax + 1];

int NODES, source, sink;

void add_edge ( const int &x, const int &y, const int &capacitate, const int &cost ) {
    int sz = edges.size ();
    edges.push_back ( { x, y, capacitate, cost } );
    adj[x].push_back ( sz );
    edges.push_back ( { y, x, 0, -cost } );
    adj[y].push_back ( sz + 1 );
}

int bellman ( int start = source ) {
    for ( int i = 0; i < NODES; i++ )
        inQ[i] = false, dist[i] = oo;

    queue < int > q;

    q.push ( start );
    dist[start] = 0;
    while ( ! q.empty () ) {
        int node = q.front ();
        q.pop ();
        inQ[node] = false;
        for ( int x: adj[node] ) {
            edge e = edges[x];
            int v = e.b;
            if ( e.flux > 0 && dist[v] > dist[node] + e.cost ) {
                dist[v] = dist[node] + e.cost;
                if ( inQ[v] == false ) {
                    inQ[v] = true;
                    q.push ( v );
                }
            }
        }
    }
    return ( dist[sink] != oo );
}

int dijkstra ( int start = source ) {
    priority_queue < pair < int, int > > pq;
    for ( int i = 0; i < NODES; i++ ) {
        vis[i] = 0;
        p[i] = -1;
        p_edge[i] = -1;
        real_dist[i] = dist[i];
        fake_dist[i] = oo;
    }

    p[start] = -1;
    dist[start] = fake_dist[start] = 0;
    pq.push ( { 0, start } );
    while ( ! pq.empty () ) {
        int node = pq.top ().second;
        pq.pop ();
        if ( vis[node] == 0 ) {
            vis[node] = 1;
            for ( int x: adj[node] ) {
                edge e = edges[x];
                int v = e.b;
                if ( e.flux > 0 && fake_dist[v] > fake_dist[node] + real_dist[node] + e.cost - real_dist[v] ) {
                    fake_dist[v] = fake_dist[node] + real_dist[node] + e.cost - real_dist[v];
                    dist[v] = dist[node] + e.cost;
                    p[v] = node;
                    p_edge[v] = x;
                    pq.push ( { -fake_dist[v], v } );
                }
            }
        }
    }
    return fake_dist[sink] != oo;
}

int min_cost_flow ( int source, int sink ) {
    int maxFlow = 0, minCost = 0;
    bellman ( source );

    while ( dijkstra ( source ) ) {

        int node = sink, flow = oo, Cost = 0;

        while ( node != source ) {
            flow = min ( flow, edges[p_edge[node]].flux );
            Cost += edges[p_edge[node]].cost;
            node = p[node];
        }

        node = sink;
        while ( node != source ) {
            edges[p_edge[node]].flux -= flow;
            edges[p_edge[node] ^ 1].flux += flow;
            node = p[node];
        }

        maxFlow += flow;
        minCost += Cost * flow;
    }

    return minCost;
}

int main () {
    int n1, n2, m, v, w, x;

    fin >> n1 >> n2 >> m;
    NODES = n1 + n2 + 2;
    source = 0; sink = n1 + n2 + 1;

    for ( int i = 0; i < m; i++ ) {
        fin >> v >> w >> x;
        add_edge ( v, n1 + w, 1, x );
    }

    for ( int i = 1; i <= n1; i++ )
        add_edge ( source, i, 1, 0 );

    for ( int i = 1; i <= n2; i++ )
        add_edge ( n1 + i, sink, 1, 0 );

    int cnt = 0, cost;
    cost = min_cost_flow ( source, sink );

    for ( int i = 0; i < m; i++ )
        if ( edges[2 * i].flux == 0 )
            cnt++;

    fout << cnt << ' ' << cost << '\n';

    for ( int i = 0; i < m; i++ )
        if ( edges[2 * i].flux == 0 )
            fout << i + 1 << ' ';

    return 0;
}