#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
题解:先写网络流,跑的还挺快。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 #include<cstring> 7 #define PAU putchar(' ') 8 #define ENT putchar('\n') 9 using namespace std; 10 const int maxn=100000+10,maxm=2000000+10,inf=-1u>>1; 11 struct isap{ 12 struct ted{int x,y,w;ted*nxt,*re;}adj[maxm],*fch[maxn],*cur[maxn],*ms; 13 int gap[maxn],d[maxn],ret[maxn],n,S,T; 14 void init(int n){memset(d,-1,sizeof(d));ms=adj;this->n=n;return;} 15 void add(int x,int y,int w){ 16 *ms=(ted){x,y,w,fch[x],ms+1};fch[x]=ms++; 17 *ms=(ted){y,x,0,fch[y],ms-1};fch[y]=ms++; 18 return; 19 } 20 void bfs(){ 21 queue<int>Q;Q.push(T);d[T]=0; 22 while(!Q.empty()){ 23 int x=Q.front();Q.pop(); 24 for(ted*e=fch[x];e;e=e->nxt){ 25 int v=e->y;if(d[v]<0)d[v]=d[x]+1,Q.push(v); 26 } 27 }return; 28 } 29 int mxflow(int S,int T){ 30 this->S=S;this->T=T;bfs();int flow=0,k=S;ted*e; 31 for(int i=1;i<=n;i++)gap[d[i]]++,cur[i]=fch[i]; 32 while(d[S]<n){ 33 if(k==T){int mi=inf,p; 34 for(int i=S;i!=T;i=cur[i]->y)if(cur[i]->w<mi)mi=cur[i]->w,p=i; 35 for(int i=S;i!=T;i=cur[i]->y)cur[i]->w-=mi,cur[i]->re->w+=mi;flow+=mi;k=p; 36 }for(e=cur[k];e;e=e->nxt)if(e->w&&d[k]==d[e->y]+1)break; 37 if(e){cur[k]=e;k=e->y;ret[e->y]=e->x;} 38 else{if(--gap[d[k]]==0)break;cur[k]=fch[k];int mi=n; 39 for(ted*e=fch[k];e;e=e->nxt)if(e->w&&d[e->y]<mi)mi=d[e->y]; 40 d[k]=mi+1;gap[d[k]]++;if(k!=S)k=ret[k]; 41 } 42 }return flow; 43 } 44 int print(int x){ 45 for(ted*e=fch[x];e;e=e->nxt)if(!e->w&&!((e-adj)&1))return e->y;return 0; 46 } 47 }sol; 48 inline int read(){ 49 int x=0,sig=1;char ch=getchar(); 50 while(!isdigit(ch)){if(ch=='-')sig=-1;ch=getchar();} 51 while(isdigit(ch))x=10*x+ch-'0',ch=getchar(); 52 return x*=sig; 53 } 54 inline void write(int x){ 55 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 56 int len=0,buf[15];while(x)buf[len++]=x%10,x/=10; 57 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 58 } 59 int n1,n2,m; 60 void init(){ 61 n1=read();n2=read();m=read();sol.init(n1+n2+2);int x,y,w,S=n1+n2+1,T=n1+n2+2; 62 for(int i=1;i<=n1;i++)sol.add(S,i,1); 63 for(int i=n1+1;i<S;i++)sol.add(i,T,1); 64 for(int i=1;i<=m;i++)x=read(),y=read()+n1,sol.add(x,y,1); 65 write(sol.mxflow(S,T));ENT;int tmp; 66 for(int i=1;i<=n1;i++)write((tmp=sol.print(i))?tmp-n1:0),PAU; 67 return; 68 } 69 void work(){ 70 return; 71 } 72 void print(){ 73 return; 74 } 75 int main(){init();work();print();return 0;}