Cod sursa(job #1172041)

Utilizator teoionescuIonescu Teodor teoionescu Data 16 aprilie 2014 18:13:23
Problema Cuplaj maxim in graf bipartit Scor 90
Compilator cpp Status done
Runda Arhiva educationala Marime 2.12 kb
#include<fstream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
ifstream in("cuplaj.in");
ofstream out("cuplaj.out");
const int Nmax = 10001;
const int Emax = 100001;
vector<int> G[2*Nmax+2],C[2*Nmax+2],Inv[2*Nmax+2];
int N,M,E,S,D,MF;
int pred[2*Nmax+2],ctl[2*Nmax+2];
int addpath(int x){
    int p=x;
    int Min=C[x][0];
    if(!Min) return 0;
    while(p!=S){
        Min=min(Min,C[pred[p]][ctl[p]]);
        if(!Min) return 0;
        p=pred[p];
    }
    C[x][0]-=1;
    C[D][x-N-1]+=1;
    p=x;
    while(p!=S){
        C[pred[p]][ctl[p]]-=1;
        C[p][ Inv[pred[p]][ctl[p]] ]+=1;
        p=pred[p];
    }
    return 1;
}
queue<int> q;
int bfs(){
    memset(pred,0,sizeof(pred)); pred[S]=S;
    q.push(S);
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=0;i<G[x].size();i++){
            if(!pred[G[x][i]] && C[x][i]>0){
                pred[G[x][i]]=x;
                ctl[G[x][i]]=i;
                q.push(G[x][i]);
            }
        }
    }
    return pred[D]!=0;
}
int main(){
    in>>N>>M>>E;
    S=N+M+1,D=N+M+2;
    for(int i=1;i<=N;i++){
        G[S].push_back(i);
        C[S].push_back(1);
        G[i].push_back(S);
        C[i].push_back(0);
        Inv[S].push_back(G[i].size()-1);
        Inv[i].push_back(G[S].size()-1);
    }
    for(int i=1;i<=M;i++){
        G[N+i].push_back(D);
        C[N+i].push_back(1);
        G[D].push_back(N+i);
        C[D].push_back(0);
        Inv[N+i].push_back(G[D].size()-1);
        Inv[D].push_back(G[N+i].size()-1);
    }
    for(int i=1;i<=E;i++){
        int x,y;
        in>>x>>y;
        G[x].push_back(N+y);
        C[x].push_back(1);
        G[N+y].push_back(x);
        C[N+y].push_back(0);
        Inv[x].push_back(G[N+y].size()-1);
        Inv[N+y].push_back(G[x].size()-1);
    }
    while(bfs()){
        for(int i=1;i<=M;i++) if(pred[N+i]) MF+=addpath(N+i);
    }
    out<<MF<<'\n';
    for(int i=1;i<=N;i++){
        for(int j=0;j<G[i].size();j++){
            if(G[i][j]<=M+N && !C[i][j]) out<<i<<' '<<G[i][j]-N<<'\n';
        }
    }
    return 0;
}