Cod sursa(job #1896115)

Utilizator mariakKapros Maria mariak Data 28 februarie 2017 14:14:20
Problema Cuplaj maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.49 kb
#include <bits/stdc++.h>
#define maxN 605
#define inf 2000000002
#define pii pair <int, int>

FILE *fin  = freopen("cmcm.in", "r", stdin);
FILE *fout = freopen("cmcm.out", "w", stdout);

using namespace std;
int N, M, S, D, E, ans;
struct Node{
    int dp1, dp2, dad;
    vector <pii> adj;
} G[maxN];
bitset <maxN> vis;
queue <int> Q;
struct comp{
    bool operator () (const pii &a, const pii &b){
        return a.second > b.second;
    }
};
priority_queue <pii, vector <pii>, comp> q;
int r[maxN][maxN]; /// edge rezidual cost
int edge[maxN][maxN];

void read(){
    int u, v, cost;
    scanf("%d %d %d", &N, &M, &E);
    for(int i = 0; i < E; ++ i){
        scanf("%d %d %d", &u, &v, &cost);
        v += N;
        edge[u][v] = i + 1;
        G[u].adj.push_back(make_pair(v, cost));
        G[v].adj.push_back(make_pair(u, -cost));
        r[u][v] = 1;
    }
    // create graph
    S = 0, D = N + M + 1;
    for(int i = 1; i <= N; ++ i){
        G[i].adj.push_back(make_pair(S, 0));
        G[S].adj.push_back(make_pair(i, 0));
        r[S][i] = 1;
    }
    for(int i = N + 1; i <= N + M; ++ i){
        G[i].adj.push_back(make_pair(D, 0));
        G[D].adj.push_back(make_pair(i, 0));
        r[i][D] = 1;
    }
}

void initdp1(){
    for(int i = 1; i <= D; ++ i)
        G[i].dp1 = inf;
}

void Bellman_Ford(){
    initdp1();
    G[S].dp1 = 0, vis.set(S);

    for(Q.push(S); Q.empty() == false; Q.pop()){
        int u = Q.front(); vis.reset(u);
        for(pii next : G[u].adj){
             int v = next.first, cost = next.second;
             if(r[u][v] != 0 && G[v].dp1 > G[u].dp1 + cost){
                G[v].dp1 = G[u].dp1 + cost;
                if(v != D && !vis.test(v)){
                    vis.set(v);
                    Q.push(v);
                }
            }
        }
    }
}

void init(){
    for(int i = 1; i <= D; ++ i)
        G[i].dp2 = inf;
}

bool Dijkstra() {
    init();
    G[S].dp2 = 0;

    for(q.push(make_pair(S, 0)); q.empty() == false;) {
        pii u = q.top(); q.pop();
        if(G[u.first].dp2 != u.second)
            continue;

        for(pii next : G[u.first].adj){
            int v = next.first, c = next.second + G[u.first].dp1 - G[v].dp1;
            if(r[u.first][v] != 0 && G[v].dp2 > G[u.first].dp2 + c){
                G[v].dp2 = G[u.first].dp2 + c;
                G[v].dad = u.first;
                if(v != D)
                    q.push(make_pair(v, G[v].dp2));
            }
        }
    }
    return (G[D].dp2 != inf);
}

void solve(){
    Bellman_Ford();
    while(Dijkstra()){
        int pathFlow = inf;
        int u = D;
        while(u != S){
            int d = G[u].dad;
            pathFlow = min(pathFlow, r[d][u]);
            u = d;
        }
        u = D;
        while(u != S){
            int d = G[u].dad;
            r[d][u] -= pathFlow;
            r[u][d] += pathFlow;
            u = d;
        }
        ans += (G[D].dp2 - G[S].dp1 + G[D].dp1) * pathFlow;
    }
}

void write(){
    int no = 0;
    for(int i = 1; i <= N; ++ i)
        for(int j = N + 1; j <= N + M; ++ j)
            if(r[i][j] != 1 && edge[i][j])
                ++ no;
    printf("%d %d\n", no, ans);
    for(int i = 1; i <= N; ++ i)
        for(int j = N + 1; j <= N + M; ++ j)
            if(r[i][j] != 1 && edge[i][j]){
                printf("%d ", edge[i][j]);
                break;
            }
}

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