二部图匹配

来源:互联网 发布:杭州小周seo 编辑:程序博客网 时间:2024/05/17 03:43

给定一个二部图,从X出发向Y连边,X中的点总会被匹配到,求当最大匹配时,Y中总会被匹配到的点。

对于每一个y,去掉(x,y)并删除y后求一次增广路。

#include<cstdio>#include<cstring>#include<string.h>#include<algorithm>#include<iostream>#include<math.h>#include<vector>using namespace std;const int maxn=1001;int nx,ny;int sy[maxn],cx[maxn],cy[maxn];vector<int>g[maxn];int ccx[maxn],ccy[maxn];int path(int u){for(int i=0;i<g[u].size();i++){int v=g[u][i];if(!sy[v]){sy[v]=1;if(!cy[v]||path(cy[v])){cx[u]=v;cy[v]=u;return 1;}}}return 0;}int match(){memset(cx,0,sizeof(cx));memset(cy,0,sizeof(cy));int ret=0;for(int i=1;i<=nx;++i)if(!cx[i]){memset(sy,0,sizeof(sy));ret+=path(i);}return ret;}int match2(int  y){memset(sy,0,sizeof(sy));for(int i=1;i<=nx;i++)ccx[i]=cx[i];for(int i=1;i<=ny;i++)ccy[i]=cy[i];sy[y]=1;int x=cy[y];cx[x]=0;cy[y]=0;int ret=path(x);for(int i=1;i<=nx;i++)cx[i]=ccx[i];for(int i=1;i<=ny;i++)cy[i]=ccy[i];return !ret;}int main(){int N,M;while(scanf("%d%d",&N,&M)!=EOF){for(int i=1;i<=N;i++){int j,k;scanf("%d",&k);g[i].clear();while(k--){scanf("%d",&j);g[i].push_back(j);}}nx=N;ny=M;match();for(int i=1;i<=ny;i++){if(cy[i]&&match2(i))printf("%d\n",i);}}return 0;}

from sysuoj.