一道二分图最大匹配裸题···但既然czq讲网络流就用最大流做一下吧···
设源点s,汇点t
从s向m个外籍连容量为1的边,m个外籍向对应的搭档连容量为1的边,再从n-m个英国向t连容量为1的边
然后跑个最大流就行了
这儿是czq骚气的dinic模板,跑挺快的
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define N 105
#define M 50000
#define INF 0x3f3f3f3f
using namespace std;
int n,m,cnt=1,head[N],s,t,dep[N],cur[N],ans;
inline int rd(){
int x=0,f=1;char c=' ';
while(c<'0' || c>'9') {if(c=='-')f=-1;c=getchar();}
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
struct EDGE{
int to,nxt,w;
}edge[M];
inline void add(int x,int y,int z){
edge[++cnt].to=y;
edge[cnt].nxt=head[x];
edge[cnt].w=z;
head[x]=cnt;
}
inline bool bfs(int s,int y){
memset(dep,0,sizeof dep);
queue<int> q;
while(!q.empty()) q.pop();
q.push(s); dep[s]=1;
while(!q.empty()){
int u=q.front(); q.pop();
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(dep[v] || !edge[i].w) continue;
dep[v]=dep[u]+1; q.push(v);
}
}
return dep[t];
}
inline int dfs(int x,int flow,int t){
if(x==t) return flow;
int used=0,tmp;
for(int i=cur[x];i;i=edge[i].nxt){
int v=edge[i].to;
if(dep[v]!=dep[x]+1) continue;
tmp=dfs(v,min(flow-used,edge[i].w),t);
edge[i].w-=tmp,edge[i^1].w+=tmp; used+=tmp;
if(used==flow) return flow;
if(edge[i].w) cur[x]=i;
}
if(!used) dep[x]=-1;
return used;
}
inline int dinic(int s,int t){
int ret=0;
while(bfs(s,t)){
memcpy(cur,head,sizeof (head));
ret+=dfs(s,INF,t);
}
return ret;
}
int main(){
m=rd();n=rd(); s=0,t=n+1;
for(int i=1;i<=m;i++) add(s,i,1),add(i,s,0);
for(int i=m+1;i<=n;i++) add(i,t,1),add(t,i,0);
while(1){
int a=rd(),b=rd();
if(a==-1 && b==-1) break;
add(a,b,1); add(b,a,0);
}
ans=dinic(s,t);
if(ans==0) return cout<<"No Solution!"<<endl,0;
printf("%d\n",ans);
for(int u=1;u<=m;u++)
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to; if(v==s) continue;
if(edge[i^1].w) printf("%d %d\n",u,v);
}
return 0;
}