UOJ #78 二分图最大匹配

时间:2022-12-24 18:13:27

#78. 二分图最大匹配

从前一个和谐的班级,有 nl 个是男生,有 nr 个是女生。编号分别为 1,…,nl 和 1,…,nr。

有若干个这样的条件:第 v 个男生和第 u 个女生愿意结为配偶。

请问这个班级里最多产生多少对配偶?

输入格式

第一行三个正整数,nl,nr,m。

接下来 m 行,每行两个整数 v,u 表示第 v 个男生和第 u 个女生愿意结为配偶。保证 1≤v≤nl,1≤u≤nr,保证同一个条件不会出现两次。

输出格式

第一行一个整数,表示最多产生多少对配偶。

接下来一行 nl 个整数,描述一组最优方案。第 v 个整数表示 v 号男生的配偶的编号。如果 v 号男生没配偶请输出 0。

样例一

input

2 2 3
1 1
1 2
2 1

output

2
2 1

explanation

1 号男生跟 2 号女生幸福地生活在了一起~

2 号男生跟 1 号女生幸福地生活在了一起~

样例二

input

2 2 2
1 1
2 1

output

1
1 0

explanation

班上一个女神一个女汉子,两个男生都去追女神。一种最优方案是:

1 号男生跟 1 号女生幸福地生活在了一起~

2 号男生孤独终生。= =||

限制与约定

1≤nl,nr≤500,1≤m≤250000。

时间限制:1s

空间限制:256MB

题解:先写网络流,跑的还挺快。

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cstring>
#define PAU putchar(' ')
#define ENT putchar('\n')
using namespace std;
const int maxn=+,maxm=+,inf=-1u>>;
struct isap{
struct ted{int x,y,w;ted*nxt,*re;}adj[maxm],*fch[maxn],*cur[maxn],*ms;
int gap[maxn],d[maxn],ret[maxn],n,S,T;
void init(int n){memset(d,-,sizeof(d));ms=adj;this->n=n;return;}
void add(int x,int y,int w){
*ms=(ted){x,y,w,fch[x],ms+};fch[x]=ms++;
*ms=(ted){y,x,,fch[y],ms-};fch[y]=ms++;
return;
}
void bfs(){
queue<int>Q;Q.push(T);d[T]=;
while(!Q.empty()){
int x=Q.front();Q.pop();
for(ted*e=fch[x];e;e=e->nxt){
int v=e->y;if(d[v]<)d[v]=d[x]+,Q.push(v);
}
}return;
}
int mxflow(int S,int T){
this->S=S;this->T=T;bfs();int flow=,k=S;ted*e;
for(int i=;i<=n;i++)gap[d[i]]++,cur[i]=fch[i];
while(d[S]<n){
if(k==T){int mi=inf,p;
for(int i=S;i!=T;i=cur[i]->y)if(cur[i]->w<mi)mi=cur[i]->w,p=i;
for(int i=S;i!=T;i=cur[i]->y)cur[i]->w-=mi,cur[i]->re->w+=mi;flow+=mi;k=p;
}for(e=cur[k];e;e=e->nxt)if(e->w&&d[k]==d[e->y]+)break;
if(e){cur[k]=e;k=e->y;ret[e->y]=e->x;}
else{if(--gap[d[k]]==)break;cur[k]=fch[k];int mi=n;
for(ted*e=fch[k];e;e=e->nxt)if(e->w&&d[e->y]<mi)mi=d[e->y];
d[k]=mi+;gap[d[k]]++;if(k!=S)k=ret[k];
}
}return flow;
}
int print(int x){
for(ted*e=fch[x];e;e=e->nxt)if(!e->w&&!((e-adj)&))return e->y;return ;
}
}sol;
inline int read(){
int x=,sig=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')sig=-;ch=getchar();}
while(isdigit(ch))x=*x+ch-'',ch=getchar();
return x*=sig;
}
inline void write(int x){
if(x==){putchar('');return;}if(x<)putchar('-'),x=-x;
int len=,buf[];while(x)buf[len++]=x%,x/=;
for(int i=len-;i>=;i--)putchar(buf[i]+'');return;
}
int n1,n2,m;
void init(){
n1=read();n2=read();m=read();sol.init(n1+n2+);int x,y,w,S=n1+n2+,T=n1+n2+;
for(int i=;i<=n1;i++)sol.add(S,i,);
for(int i=n1+;i<S;i++)sol.add(i,T,);
for(int i=;i<=m;i++)x=read(),y=read()+n1,sol.add(x,y,);
write(sol.mxflow(S,T));ENT;int tmp;
for(int i=;i<=n1;i++)write((tmp=sol.print(i))?tmp-n1:),PAU;
return;
}
void work(){
return;
}
void print(){
return;
}
int main(){init();work();print();return ;}