![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; int m,n,tot=-1,h[1005],ans=0,tp=0; struct node{ int from,next,to,rest; int last; }e[10005]; void add(int x,int y,int z){ tot++; e[tot].next=h[x]; h[x]=tot; e[tot].from=x; e[tot].to=y; e[tot].rest=z; } int dis[1005],g[1005],flow[1005]; bool vis[1005]; int bfs(int s,int t){ queue<int>q; dis[s]=0; q.push(s);vis[s]=true; while(!q.empty()){ int u=q.front();vis[u]=false;q.pop(); for(int i=h[u];i!=(-1);i=e[i].next){ if(dis[e[i].to]>dis[u]+1&&g[e[i].to]==(-1)&&e[i].rest>0){ g[e[i].to]=i; flow[e[i].to]=min(flow[u],e[i].rest); dis[e[i].to]=dis[u]+1; if(vis[e[i].to]==false){ vis[e[i].to]=true; q.push(e[i].to); } } } } } int EK(int s,int t){ while(1){ memset(dis,0x7f,sizeof(dis)); memset(vis,false,sizeof(vis)); memset(flow,0x7f,sizeof(flow)); memset(g,-1,sizeof(g)); bfs(s,t); if(g[t]==(-1))return 0; ans+=flow[t]; for(int p=t;p!=(s);p=e[g[p]].from){ e[g[p]].rest-=flow[t]; e[g[p]].last=tp; e[g[p]^1].rest+=flow[t]; } } } int main(){ memset(h,-1,sizeof(h)); cin>>n>>m; for(int i=1;i<=m;i++){ add(0,i,1); add(i,0,0); } for(int i=m+1;i<=n;i++){ add(i,n+1,1); add(n+1,i,0); }int x,y; while(scanf("%d%d",&x,&y)!=EOF){ add(x,y,1); add(y,x,0); } EK(0,n+1); if(ans==0){ cout<<"No Solution!"<<endl; exit(0); } cout<<ans<<endl; }
Well, this is the network flow problem do bipartite graph maximum matching ....
Over the water, you may be interested in doing Hungary, or network flow flavors ha