应该是二分图匹配,不过我写的是网络最大流。
dinic求二分图最大匹配:加个源点和汇点,源点连向二分图的一边所有点,二分图的另一边所有点连向汇点,很明显这样得到的最大流就是这个二分图的最大匹配。
#include<cstdio> #include<algorithm> #define rep(i,n) for(register int i=1;i<=n;i++) #define REP(i,a,b) for(register int i=a;i<=b;i++) using namespace std; const int N=105; const int M=10205; const int INF=(~0u>>1); struct edge { int to,nxt,w; edge(int to=0,int nxt=0,int w=1):to(to),nxt(nxt),w(w){} }edges[M<<1]; int n,m,cnt,st,ed,s,t,ans; int head[M<<1],d[N],q[N]; inline void addEdge(int u,int v) { edges[++cnt]=edge(v,head[u]); head[u]=cnt; edges[++cnt]=edge(u,head[v],0); head[v]=cnt; } #define cur edges[i].to inline bool bfs() { rep(i,t)d[i]=0;d[s]=1; st=ed=0;q[st++]=s; while(ed<st) { int k=q[ed++]; for(register int i=head[k];i;i=edges[i].nxt)if(edges[i].w&&!d[cur]) { d[cur]=d[k]+1;q[st++]=cur; if(cur==t)return 1; } } return 0; } inline int dinic(int x,int f) { if(x==t)return f; int res=f; for(register int i=head[x];i&&res;i=edges[i].nxt)if(edges[i].w&&d[cur]==d[x]+1) { int k=dinic(cur,min(res,edges[i].w)); if(!k)d[cur]=0; edges[i].w-=k;edges[i^1].w+=k;res-=k; } return f-res; } int main() { scanf("%d%d",&n,&m);s=n+1;t=n+2;cnt=1; int u,v; while(scanf("%d%d",&u,&v)==2)addEdge(u,v); REP(i,1,m)addEdge(s,i); REP(i,m+1,n)addEdge(i,t); int flow=0; while(bfs())while((flow=dinic(s,INF)))ans+=flow; printf("%d",ans); return 0; }