P2756 飞行员配对问题
题意:寻找最大匹配
思路:转化为二分图匹配问题
新套路:二分图匹配方案的输出:
for(int i=2;i<=tot*2;i+=2) { if(ver[i]!=sou&&ver[i^1]!=des) if(ver[i]!=des&&ver[i^1]!=sou) { if(wei[i^1]>0) { printf("%d %d\n",ver[i],ver[i^1]); } } }
稍微解释一下:就是对于寻找中介连接的边,然后判断后向边有没有流量(也就是这一条边有没有东西流过去)
代码如下:
#include <stdio.h> #include <algorithm> #include <cstring> #define INF 10000000 using namespace std; const int maxn=1000000; int head[maxn],next[maxn],wei[maxn],ver[maxn],tot; int lev[maxn],cur[maxn]; int n,m,ans,sou,des; inline void add(int x,int y,int w) { ver[++tot]=y;wei[tot]=w;next[tot]=head[x];head[x]=tot; ver[++tot]=x;wei[tot]=0;next[tot]=head[y];head[y]=tot; } inline bool bfs() { static int que[202],ql=1,qr=1; int x,v; for(int i=0;i<=n+1;i++) cur[i]=head[i],lev[i]=-1; que[ql]=sou;lev[sou]=0; for(ql=1,qr=1;ql<=qr;ql++) { x=que[ql]; for(int i=head[x];i;i=next[i]) { if(wei[i]>0&&lev[v=ver[i]]==-1) { lev[v]=lev[x]+1; que[++qr]=v; if(v==des) return true; } } } return false; } inline int dinic(int x,int flow) { if(x==des) return flow; int res=0,v,delta; for(int i=cur[x];i;i=next[i])//这里失误了,应该是cur[x]而不是cur[i] { if(wei[i]>0&&lev[x]<lev[v=ver[i]]) { delta=dinic(v,min(flow-res,wei[i])); if(delta) { wei[i]-=delta;wei[i^1]+=delta; res+=delta;if(res==flow) break; } } } if(res!=flow) lev[x]=-1; return res; } inline int maxflow() { int res=0; while(bfs()) res+=dinic(sou,INF); return res; } int main() { scanf("%d%d",&m,&n); tot=1;sou=0,des=n+1; int u,v; while(1) { scanf("%d%d",&u,&v); if(u==-1&&v==-1) break; add(u,v,1); } for(int i=1;i<=m;i++) add(sou,i,1); for(int i=m+1;i<=n;i++) add(i,des,1); ans=maxflow(); printf("%d\n",ans); for(int i=2;i<=tot*2;i+=2) { if(ver[i]!=sou&&ver[i^1]!=des) if(ver[i]!=des&&ver[i^1]!=sou) { if(wei[i^1]>0) { printf("%d %d\n",ver[i],ver[i^1]); } } } return 0; }
浙公网安备 33010602011771号