Pagini recente » Cod sursa (job #691256) | Cod sursa (job #2002476) | Istoria paginii winter-challenge-2008/runda-2 | Cod sursa (job #241556) | Cod sursa (job #228439)
Cod sursa(job #228439)
//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;
}