Cod sursa(job #1393546)

Utilizator danalex97Dan H Alexandru danalex97 Data 19 martie 2015 16:04:04
Problema Cuplaj maxim in graf bipartit Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 3.76 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;

ofstream G("cuplaj.out");

const int N = 20010;
const int M = 120010;

struct edge {
    int x,y,c[2];
    int _(int xx)
    {
        return x+y-xx;
    }
    int w(int xx,int yy)
    {
        return ( xx == x && yy == y ) ? 0 : 1;
    }
    int cap(int xx,int yy)
    {
        return w(xx,yy) == 0 ? c[0] : c[1];
    }
};

vector<int> v[N];
edge e[M];
int n,m,m2,flow,dad[N],pl[N];

int go(int x)
{
    memset(dad,0,sizeof(dad));
    memset(pl,0,sizeof(pl));
    dad[1] = -1;

    queue<int> q;
    q.push( 1 );

    while ( !q.empty() )
    {
        int x = q.front();
        q.pop();

        for (int i=0;i<int(v[x].size());++i)
        {
            int idx = v[x][i];
            int y = e[idx]._(x);
            if ( dad[ y ] == 0 && e[idx].cap(x,y) > 0 )
            {
                dad[ y ] = x;
                pl[ y ] = idx;
                q.push( y );
            }
        }
    }

    return dad[n] != 0;
}

int n1,n2;

int left_edge(int x)
{
    return 1 + x;
}

int right_edge(int x)
{
    return 1 + x + n1;
}

int rev_left_edge(int x)
{
    return x-1;
}

int rev_right_edge(int x)
{
    return x-1-n1;
}

const int Buffer=1<<13;
char Buff[Buffer]; int Next=0;

#define F stdin

int get_int()
{
    int Nbr=0;
    while( Buff[Next]<'0' || '9'<Buff[Next] )
        if ( ++Next >= Buffer ) fread(Buff,Buffer,1,F), Next=0;
    while ( '0'<=Buff[Next] && Buff[Next]<='9' )
    {
        Nbr=Nbr*10+Buff[Next]-'0';
        if ( ++Next >= Buffer ) fread(Buff,Buffer,1,F), Next=0;
    }
    return Nbr;
}


int main()
{
    freopen("cuplaj.in","r",stdin);
    n1 = get_int();
    n2 = get_int();
    m = get_int();
    for (int i=1;i<=m;++i)
    {
        e[i].x = get_int();
        e[i].y = get_int();
        e[i].c[0] = 1;
        e[i].x = left_edge(e[i].x);
        e[i].y = right_edge(e[i].y);
        v[ e[i].x ].push_back( i );
        v[ e[i].y ].push_back( i );
    }
    n = 1 + n1 + n2 + 1;
    m2 = m;
    for (int i=1;i<=n1;++i)
    {
        e[++m].x = 1;
        e[m].y = left_edge(i);
        e[m].c[0] = 1;
        v[ e[m].x ].push_back( m );
        v[ e[m].y ].push_back( m );
    }
    for (int i=1;i<=n2;++i)
    {
        e[++m].x = right_edge(i);
        e[m].y = n;
        e[m].c[0] = 1;
        v[ e[m].x ].push_back( m );
        v[ e[m].y ].push_back( m );
    }

    //go(1); for (int i=1;i<=n;++i) cerr<<dad[i]<<' ';cerr<<'\n';
    //for (int i=1;i<=n;++i) cerr<<pl[i]<<' ';cerr<<'\n';
    while ( go(1) )
        for (int i=0;i<int(v[n].size());++i)
        {
            int idx = v[n][i];
            int x = e[idx]._(n);

            //cerr<<e[idx].cap(x,n) <<'\n';
            if ( dad[x] != 0 && e[idx].cap(x,n) > 0 )
            {
                int cap = e[idx].cap(x,n);
                for (int i=x;i!=1;i=dad[i])
                {
                    cap = min(cap,e[pl[i]].cap(dad[i],i));
                    if ( cap == 0 ) break;
                }
                if ( cap == 0 ) break;
                for (int i=x;i!=1;i=dad[i])
                {
                    int j = e[pl[i]].w(dad[i],i);
                   // cerr<<j<<'\n';
                    e[pl[i]].c[j] -= cap;
                    e[pl[i]].c[1-j] += cap;
                }
                int j = e[idx].w(x,n);
                e[idx].c[j] -= cap;

                flow += cap;
            }
        }

    G<<flow<<'\n';
    for (int i=1;i<=m2;++i)
        if ( e[i].c[0] == 0 )
        {
            //cerr<<e[i].x<<' '<<e[i].y<<'\n';
            G<<rev_left_edge(e[i].x)<<' '<<rev_right_edge(e[i].y)<<'\n';
        }
}