题目:Warm up 2
题意:有横竖两种方式放着的多米诺骨牌,相同方向的不可能重叠,但是横放和竖放
的牌可能重叠。移走重叠的牌使剩下的牌最多。
分析:二分图匹配:最大独立集=顶点数-最大匹配数
横放的为一个点集,竖放的为一个点集。
代码:
#include<cstdio> #include<iostream> #include<cstring> using namespace std; struct node { int x1,y1; int x2,y2; }hori[1010],ver[1010]; int g[1010][1010]; int vis[1010]; int match[1010]; int m,n; bool dfs(int u) { int i; for(i=0;i<m;i++) { if(g[u][i] && !vis[i]) { vis[i]=true; if(match[i]==-1||dfs(match[i])) { match[i]=u; return true; } } } return false; } int main() { int i,j,cnt,ans; while(scanf("%d%d",&n,&m)&&n&&m) { memset(match,-1,sizeof(match)); memset(g,0,sizeof(g)); cnt=0; for(i=0;i<n;i++) { scanf("%d%d",&hori[i].x1,&hori[i].y1); hori[i].x2=hori[i].x1+1; hori[i].y2=hori[i].y1; cnt++; } for(i=0;i<m;i++) { scanf("%d%d",&ver[i].x1,&ver[i].y1); ver[i].x2=ver[i].x1; ver[i].y2=ver[i].y1+1; cnt++; } //printf("cnt=%d ",cnt); for(i=0;i<n;i++) { for(j=0;j<m;j++) { if(hori[i].x1==ver[j].x1 && hori[i].y1==ver[j].y1) g[i][j]=true; else if(hori[i].x2==ver[j].x1 && hori[i].y2==ver[j].y1) g[i][j]=true; else if(hori[i].x1==ver[j].x2 && hori[i].y1==ver[j].y2) g[i][j]=true; else if(hori[i].x2==ver[j].x2 && hori[i].y2==ver[j].y2) g[i][j]=true; } } ans=0; for(i=0;i<n;i++) { memset(vis,0,sizeof(vis)); if(dfs(i)) ans++; } //printf("ans=%d ",ans); printf("%d ",cnt-ans); } return 0; }