uva 12549(二分图)
二分图可以去处理一对多,或多对一但只统计为数量为1的问题。这里是多个横坐标对应一个纵坐标,但只取1。这个题我写完后想到了2-set。老了啊,多长时间没写二分图,连板子都记错了。
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; const int maxn=200; int g[maxn][maxn]; pair<int,int> id[maxn][maxn]; int t,n,m,nn,r,c; int mapp[maxn][maxn]; int match[maxn]; int vis[maxn]; bool dfs(int x) { for(int i=1;i<=c;i++) { if(g[x][i]==1&&!vis[i]) { vis[i]=1; if(match[i]==-1||dfs(match[i])) { match[i]=x; return 1; } } } return 0; } void init() { memset(mapp,0,sizeof(mapp)); memset(match,-1,sizeof(match)); memset(g,0,sizeof(g)); memset(vis,0,sizeof(vis)); } int main() { scanf("%d",&t); while(t--) { init(); scanf("%d%d",&m,&n); scanf("%d",&nn); int a,b; for(int i=1; i<=nn; i++) { scanf("%d%d",&a,&b); mapp[a][b]=1; } scanf("%d",&nn); for(int i=1; i<=nn; i++) { scanf("%d%d",&a,&b); mapp[a][b]=-1; } r=0; for(int i=1; i<=m; i++) { int flag=0; for(int j=1; j<=n; j++) { if(mapp[i][j]==1) { if(!flag) { flag=1; r++; } id[i][j].first=r; } else if(mapp[i][j]==-1) flag=0; } } c=0; for(int j=1; j<=n; j++) { int flag=0; for(int i=1; i<=m; i++) { if(mapp[i][j]==1) { if(!flag) { flag=1; c++; } id[i][j].second=c; } else if(mapp[i][j]==-1) flag=0; } } for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) { if(mapp[i][j]==1) g[id[i][j].first][id[i][j].second]=1; } int ans=0; for(int i=1;i<=r;i++) { memset(vis,0,sizeof(vis));//防止横坐标再次匹配已经匹配但是不行的纵坐标 if(dfs(i)) ans++; } printf("%d\n",ans); } return 0; }
浙公网安备 33010602011771号