Cod sursa(job #134066)

Utilizator peanutzAndrei Homorodean peanutz Data 10 februarie 2008 16:06:56
Problema Paznici2 Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.57 kb
#include <stdio.h>
#include <vector>
#include <string.h>
#include <queue>

using namespace std;

#define pb push_back
#define sz size()
#define NMAX 410
#define INFI 0x3f3f3f3f

int n;
int cost[NMAX][NMAX];
short cap[NMAX][NMAX], aux[NMAX][NMAX];
int sink, source, until;
int _min;
vector<int> g[NMAX];

void read()
{
     scanf("%d", &n);
     until = 2*n;
     int i, j;
     for(i = 1; i <= n; ++i)
           for(j = 1; j <= n; ++j)
                 scanf("%d", &cost[i][n+j]), cost[n+j][i] = -cost[i][n+j], cap[i][n+j] = 1;
    source = until+3;
    sink = until+4;
    for(i = 1; i <= n; ++i)
        cap[source][i] = 1, cap[i+n][sink] = 1;
}

int bf()
{
    queue<int> q;
    int i, x, t[NMAX], dist[NMAX];
    memset(t, 0, sizeof(t));
    memset(dist, INFI, sizeof(dist));
    q.push(source);
    dist[source] = 0;
    while(!q.empty())
    {
        x = q.front(), q.pop();
        for(i = 1; i <= sink; ++i)
            if(cap[x][i] && dist[i] > dist[x] + cost[x][i])
            {
                dist[i] = dist[x] + cost[x][i];
                t[i] = x;
                q.push(i);
            }
    }
    if(dist[sink] == 1061109567)
        return -1;
    for(i = sink; i != source; i = t[i])
        --cap[t[i]][i], ++cap[i][t[i]];
    return dist[sink];
}

int flux()
{
    int aux, c = 0;
    while(1)
    {
        aux = bf();
        //printf("%d\n", aux);
        if(aux == -1) break;
    }
    int i, j;
    for(i = 1; i <= n; ++i)
        for(j = 1; j <= n; ++j)
            c += cost[i][j+n] * (!cap[i][j+n] && cap[j+n][i]);//, printf("%d %d %d\n", i, j+n, cap[i][j+n]);
    return c;
}

int mate[NMAX];

int main()
{
    freopen("paznici2.in", "r", stdin);
    freopen("paznici2.out", "w", stdout);

    read();

    _min = flux();
    memcpy(aux, cap, sizeof(cap));
    printf("%d\n", _min);

    int i, j;
    int aux1, aux2, z;
    for(i = 1; i <= n; ++i)
        for(j = 1; j <= n; ++j)
            if(cap[j+n][i])
            {
                mate[i] = j+n;
                mate[j+n] = i;
                break;
            }
    for(j = 1; j <= n; ++j)
    {
        for(i = 1; i <= n; ++i)
        {
            if(aux[j+n][i] && !aux[i][j+n])
                g[j].pb(i);
            else
            {
                cap[source][mate[j+n]] = 1;
                cap[mate[j+n]][source] = 0;
                cap[mate[j+n]][j+n] = 0;
                cap[j+n][mate[j+n]] = 0;

                cap[i][mate[i]] = 0;
                cap[mate[i]][i] = 0;
                cap[mate[i]][sink] = 1;
                cap[sink][mate[i]] = 0;
                for(z = 1; z <= n; ++z)
                    cap[i][n+z] = 0, cap[n+z][i] = 0,
                    cap[z][n+j] = 0, cap[n+j][z] = 0;

                cap[i][j+n] = 0;
                cap[source][i] = 0;
                cap[i][source] = 0;
                cap[j+n][sink] = 0;
                cap[sink][j+n] = 0;
                //printf("i=%d j=%d cost[i][j+n]=%d  flux=%d\n", i, j, cost[i][j+n], flux());

                if(_min == flux() + cost[i][j+n])
                {
                    g[j].pb(i);
                    memcpy(cap, aux, sizeof(aux));
                }
                else
                {
                    memcpy(cap, aux, sizeof(aux));
                }
            }
        }
    }
    vector<int> :: iterator it;
    for(i = 1; i <= n; ++i)
    {
        printf("%d ", g[i].sz);
        for(it = g[i].begin(); it != g[i].end(); ++it) printf("%d ", *it);
        printf("\n");
    }
    return 0;
}