hdu 1507 Uncle Tom's Inherited Land* 最大匹配
来源:互联网 发布:羊绒围巾 牌子 知乎 编辑:程序博客网 时间:2024/05/16 08:12
#include <cstdio>#include <cstring>#include <cmath>#include <vector>#include <algorithm>#include <iostream>using namespace std;const int maxn=10010;const int maxc=110;vector<int>e[maxn];int map[maxc][maxc];int vis[maxn],pre[maxn];int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};int find(int u)//判断增广路是否存在,匈牙利算法{ int i,j,v; for(i=0;i<e[u].size();i++) { v=e[u][i]; if(!vis[v]) { vis[v]=1; if(pre[v]==-1||find(pre[v])) { pre[v]=u; return 1; } } } return 0;}int main(){ int n,m,num; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0)break; scanf("%d",&num); int i,j,k,a,b,x,y,x1,y1,x2,y2; memset(map,0,sizeof(map)); for(i=0;i<num;i++) { scanf("%d%d",&a,&b); map[a][b]=1; } for(i=1;i<=n*m;i++) e[i].clear(); for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(!map[i][j]&&(i+j)%2) { for(k=0;k<4;k++) { x=i+dir[k][0]; y=j+dir[k][1]; if(x<=0||y<=0||x>n||y>m||map[x][y])continue; e[(i-1)*m+j].push_back(((x-1)*m+y)); } } } } int ans=0; memset(pre,-1,sizeof(pre)); for(i=1;i<=n*m;i++) { memset(vis,0,sizeof(vis)); ans+=find(i); } printf("%d\n",ans); for(i=1;i<=n*m;i++) { if(pre[i]==-1)continue; if(pre[i]%m==0){x1=pre[i]/m;y1=m;} else{x1=pre[i]/m+1;y1=pre[i]%m;} if(i%m==0){x2=i/m;y2=m;} else{x2=i/m+1;y2=i%m;} printf("(%d,%d)--(%d,%d)\n",x1,y1,x2,y2); } printf("\n"); } return 0;}/* n*m的矩阵,标号1~n*m,则以相邻空白格的编号建边,则边表示的就是可选的1*2的格子。 分二部图:由于横纵坐标相加为奇数的点,跟它相邻的必定是横纵坐标相加为偶数的点,且所有奇数点加相邻偶数点覆盖所有图上的点。由此我们可以从奇数点到偶数点建二部图。 最大匹配:二分图G中,找出边数最大的子图M,使得M中各条边均无公共顶点,则M为最大匹配。 所求答案ans=最大匹配数,因为所求情况必定符合匹配,因为不能有覆盖的格子,因而最大匹配数就是所求最大的1*2格数 最后pre记录的符合最大匹配的点和它的相连点,即所求边*/