Cod sursa(job #444456)

Utilizator toni2007Pripoae Teodor Anton toni2007 Data 20 aprilie 2010 15:23:18
Problema Cuplaj maxim de cost minim Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 7.13 kb
#include <stdio.h>
#include <vector>
#include <bitset>
#include <set>
#include <algorithm>
#include <cassert>

using namespace std;

#define maxN    610
#define oo      1000000
#define X       20000

struct edge {
    int who, cost, chosed;
};

bitset <maxN> visible, viz;
vector <int> RS, RT, Solv;
vector <edge> G[maxN], V[maxN];
set <int> Z, T_Z, Z_I_T;
int N, M, E, pred[maxN], Q[maxN], st, dr, y[maxN], Cost[maxN], Sol_cuplaj;
bool Z_RT;

void print () {
    int i, j;
    /*
    printf("*************************************************************\n");
    for (i = 1; i <= N + M; ++ i) {
        for (j = 0; j < (int) G[i].size(); ++ j)
            printf("[%d %d %d]", G[i][j].who, G[i][j].cost, G[i][j].chosed);
        puts("");
    }*/

    //printf("_________________________________\n");
    for (i = N + 1; i <= N + M; ++ i)
        for (j = 0; j < (int) G[i].size(); ++ j)
            if (G[i][j].chosed) {
                Solv.push_back(G[i][j].cost);
            }
    //printf("*************************************************************\n");
}

void compute_rs () {
    visible.reset(); RS.clear();

    for (int i = N + 1; i <= N + M; ++ i)
        for (int j = 0; j < (int) G[i].size(); ++ j)
            if (G[i][j].chosed)
                visible[G[i][j].who] = 1;
    for (int i = 1; i <= N; ++ i)
        if (! visible[i])
            RS.push_back(i);
}

void compute_rt () {
    visible.reset(); RT.clear(); Z_RT = 0;

    for (int i = N + 1; i <= N + M; ++ i)
        for (int j = 0; j < (int) G[i].size(); ++ j)
            if (G[i][j].chosed)
                visible[i] = 1;

    for (int i = N + 1; i <= N + M; ++ i)
        if (!visible[i])
            RT.push_back(i);

}

void bf () {
    int now;

    viz.reset(); Z.clear();

    for (int i = 1; i <= N + M; ++ i) {
        viz[i] = 0;
        pred[i] = i;
    }

    st = dr = 0;

    for (int i = 0; i < (int) RS.size(); ++ i) {
        Q[dr ++] = RS[i];
        viz[RS[i]] = 1;
    }

    for (; st < dr;) {
        now = Q[st ++];
        for (int j = 0; j < (int) G[now].size(); ++ j) {
            if (G[now][j].chosed && !viz[G[now][j].who]) {
            //    printf("now = %d, G[now][j].who = %d G[now][j].chosed = %d\n", now, G[now][j].who, G[now][j].chosed);
                viz[G[now][j].who] = 1;
                pred[G[now][j].who] = now;
                Q[dr ++] = G[now][j].who;
            }
        }
    }

    for (int i = 1; i <= N + M; ++ i)
        if (viz[i]) {
    //        printf("i = %d ", i);
            Z.insert(i);
        }
}

bool matching () {
    int i, next, now, Sol, c2, c3, c1;

    compute_rs();
    compute_rt();
    bf();

    T_Z.clear(); Z_I_T.clear();
 
    for (i = 0; i < (int) RT.size(); ++ i)
        Z_RT |= (Z.find(RT[i]) != Z.end());

    for (i = N + 1; i <= N + M; ++ i)
        T_Z.insert(i);
  
    for (set <int> :: iterator it = Z.begin(); it != Z.end(); ++ it)
        T_Z.erase(*it);
    
    for (i = N + 1; i <= N + M; ++ i)
        if (Z.find(i) != Z.end())
            Z_I_T.insert(i);
/*
    printf("RS: ");
    for (i = 0; i < (int) RS.size(); ++ i)
        printf("%d ", RS[i]);
    puts("");
    printf("RT: ");
    for (int j = 0; j < (int) RT.size(); ++ j)
        printf("%d ", RT[j]);
    puts("");
    printf("Z: ");
    for (set <int> :: iterator it = Z.begin(); it != Z.end(); ++ it)
        printf("%d ", *it);
    puts("");

    printf("T_Z: ");
    for (set <int> :: iterator it = T_Z.begin(); it != T_Z.end(); ++ it)
        printf("%d ", *it);
    puts("");
 
    printf("Z_I_T: ");
    for (set <int> :: iterator it = Z_I_T.begin(); it != Z_I_T.end(); ++ it)
        printf("%d ", *it);
    puts("");

    printf("Z_RT : %d\n", (int) Z_RT);

    printf("G: ");

    for (i = 1; i <= N; ++ i)
        for (int j = 0; j < (int) G[i].size(); ++ j)
            if (G[i][j].chosed)
                printf("%d -> %d ", i, G[i][j].who);
            else
                printf("%d <- %d ", i, G[i][j].who);
    printf("\n");
*/
    if (Z_RT) {
//        fprintf(stderr, "OK");
        for (; dr && Q[dr - 1] <= N; -- dr);
        assert(dr);

        for (now = Q[dr - 1]; pred[now] != now; now = pred[now]) {
            next = pred[now];
            for (i = 0; i < (int) G[now].size(); ++ i)
                if (G[now][i].who == next) {
                    if (G[now][i].chosed)
                        Sol_cuplaj --;
                    else
                        Sol_cuplaj ++;
                    G[now][i].chosed ^= 1;
                }
            for (i = 0; i < (int) G[next].size(); ++ i)
                if (G[next][i].who == now) {
        //            if (G[next][i].chosed)
         //               Sol_cuplaj --;
           //         else
             //           Sol_cuplaj ++;
                    G[next][i].chosed ^= 1;
                }
        }
    } else {
        Sol = oo; c1 = 0; c2 = 0; c3 = 0;

        for (now = 1; now <= N; ++ now) {
            if (Z.find(now) == Z.end()) continue;
            for (int j = 0; j < (int) V[now].size(); ++ j)
                if (T_Z.find(V[now][j].who) != T_Z.end() && ! V[now][j].chosed) {

                    if (Cost[V[now][j].cost] - y[now] - y[V[now][j].who] < Sol) {
                        Sol = Cost[V[now][j].cost] - y[now] - y[V[now][j].who];
                        c1 = now;
                        c2 = V[now][j].who;
                        c3 = V[now][j].cost;
                    }
                }
        }

//        printf("c1 = %d c2 = %d delta = %d\n", c1, c2, Sol);
//        if (Sol == oo)  return 0;

        for (i = 1; i <= N; ++ i)
            if (Z.find(i) != Z.end())
                y[i] += Sol;
        for (i = N + 1; i <= N + M; ++ i)
            if (Z.find(i) != Z.end())
                y[i] -= Sol;
        G[c1].push_back((edge) {c2, c3, 1});
        G[c2].push_back((edge) {c1, c3, 0}); 

        for (i = 0; i < (int) V[c2].size(); ++ i)
            if (V[c2][i].who == c1)
                V[c2][i].chosed = 1;

        for (i = 0; i < (int) V[c1].size(); ++ i)
            if (V[c1][i].who == c2)
                V[c1][i].chosed = 1;
    }

//    print();
 /*
    printf("G: ");

    for (i = 1; i <= N; ++ i)
        for (int j = 0; j < (int) G[i].size(); ++ j)
            if (G[i][j].chosed)
                printf("%d -> %d ", i, G[i][j].who);
            else
                printf("%d <- %d ", i, G[i][j].who);
    printf("\n");


    fprintf(stdout, "Sol = %d\n", Sol_cuplaj);
    for (i = 1; i <= N; ++ i)
        fprintf(stdout, "%d ", y[i]);
    puts("");
    for (i = 1; i <= M; ++ i)
        fprintf(stdout, "%d ", y[i + N]);
    puts("");
    puts("");*/
    return 1;
}

int main () {
    int a, b, c, i;

    freopen("cmcm.in", "r", stdin);
    freopen("cmcm.out", "w", stdout);

    scanf("%d%d%d", &N, &M, &E);

    for (i = 1; i <= E; ++ i) {
        scanf("%d%d%d", &a, &b, &Cost[i]);
        Cost[i] += X;
        V[a].push_back((edge) {b + N, i, 0});
    }

    for (i = 0; matching () && Sol_cuplaj < min(N, M); ++ i);

    print();

    sort(Solv.begin(), Solv.end());

    int sol_cost = 0;

    for (i = 0; i < (int) Solv.size(); ++ i)
        sol_cost += Cost[Solv[i]] - X;

    printf("%d %d\n", Solv.size(), sol_cost);
    for (i = 0; i < (int) Solv.size(); ++ i)
        printf("%d ", Solv[i]);
}