Cod sursa(job #228439)

Utilizator mihai_floreaFlorea Mihai Alexandru mihai_florea Data 7 decembrie 2008 11:22:15
Problema Cuplaj maxim in graf bipartit Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 2.74 kb
//Algoritmul Hopcroft-Karp pt cuplaj maximal in graf bipartit
//O(E*sqrt(V))  ,V=nr de noduri,E=nr de muchi
#include <vector>
#include <fstream>
#include <queue>
using namespace std;
const int NMAX=10005;
int T,N,M,E,st[NMAX],dr[NMAX],niv[NMAX*2];
vector<int> a[NMAX];
ifstream f("cuplaj.in");
ofstream g("cuplaj.out");
void read(){
     int i,j;
     f>>M>>N>>E;
     while (E--){
           f>>i>>j;
           a[i].push_back(M+j);
           }
     }
queue<int> q;
int t[2*NMAX];
bool u[NMAX*2],ok,viz[NMAX*2];
void df(int vf){
    viz[vf]=true;
    vector<int>::iterator it;
    if (vf<=M){
      for (it=a[vf].begin();it!=a[vf].end();++it)
       if (dr[vf]!=*it && u[*it]==false)
        if (!viz[*it]) 
         t[*it]=vf,df(*it);}
     else
      if (vf>M && st[vf-M]==0){
        ok=true;
        int w=1,i,x=vf;
        for (i=niv[vf];i>0;i--){
            if (w==1){
             st[x-M]=t[x];
             dr[t[x]]=x;}
            w=1-w;
            u[x]=true;
            x=t[x];}
       // return;
        }
      else
      if ( u[st[vf-M]]==false) 
       if (!viz[st[vf-M]])
       t[st[vf-M]]=vf,df(st[vf-M]); 
    
    }
void solve(){
    int i,sol=0;
    bool gasit;
    vector<int>::iterator it;
    //formam un cuplaj oarecare folosind greedy
    for (i=1;i<=M;++i)
        for (it=a[i].begin();it!=a[i].end();it++)
          if (st[*it-M]==0) {
            st[*it-M]=i;
            dr[i]=*it;
            ++sol;
            break;
            }
    gasit=true;
    while (gasit){ 
    //folosind BFS calculam d=lungimea minima a unui drum de crestere
    gasit=false;
    memset(niv,-1,sizeof(niv));
    for (i=1;i<=M;++i)
      if (dr[i]==0) q.push(i),niv[i]=0;
    while (!q.empty()){
           i=q.front();
           q.pop();
           if (i<=M)
            for (it=a[i].begin();it!=a[i].end();++it)
             if (dr[i]!=*it && niv[*it]==-1){
               q.push(*it),niv[*it]=niv[i]+1;
               if (st[*it-M]==0 ) gasit=true;
              }
           if (i>M)
            if (st[i-M]!=0)
             if (niv[st[i-M]]==-1) 
              q.push(st[i-M]),niv[st[i-M]]=niv[i]+1;
            }  
    if (gasit) {
    //folosind DFS gasim o multime maximala de drumuri de crestere de lungime d si le
    //"adaugam" la cuplaj
    memset(u,false,sizeof(u));
    for (i=1;i<=M;++i)
      if (dr[i]==0) {u[i]=true;
                     memset(viz,false,sizeof(viz));
                     ok=false; 
                     df(i); 
                     if (ok) ++sol;}
                  }
                     
      }

    g<<sol<<'\n';
    for (i=1;i<=M;++i)
     if (dr[i]!=0)
      g<<i<<' '<<dr[i]-M<<'\n';
}
int main(){
    read();
    solve();
    return 0;
}