题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1507
思路:这题关键是建图,我们可以把坐标映射建双向图,最后求得的最大匹配数/2就ok了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 #define MAXN 10010 8 vector<int>map[MAXN]; 9 int n,m,k; 10 bool mark[MAXN]; 11 bool visited[111][111]; 12 int ly[MAXN]; 13 14 int dfs(int u) { 15 for(int i=0; i<map[u].size(); i++) { 16 int v=map[u][i]; 17 if(!mark[v]) { 18 mark[v]=true; 19 if(ly[v]==-1||dfs(ly[v])) { 20 ly[v]=u; 21 return 1; 22 } 23 } 24 } 25 return 0; 26 } 27 28 29 int MaxMatch() { 30 int res=0; 31 memset(ly,-1,sizeof(ly)); 32 for(int i=1; i<=n*m; i++) { 33 memset(mark,false,sizeof(mark)); 34 res+=dfs(i); 35 } 36 return res; 37 } 38 39 40 int main() { 41 // freopen("1.txt","r",stdin); 42 int u,v; 43 while(scanf("%d%d",&n,&m),(n+m)) { 44 for(int i=1; i<=n*m; i++)map[i].clear(); 45 scanf("%d",&k); 46 memset(visited,false,sizeof(visited)); 47 for(int i=1; i<=k; i++) { 48 scanf("%d%d",&u,&v); 49 visited[u][v]=true; 50 } 51 for(int i=1; i<=n; i++) { 52 for(int j=1; j<=m; j++) { 53 if(visited[i][j])continue; 54 if(i+1<=n&&!visited[i+1][j]) { 55 map[(i-1)*m+j].push_back(i*m+j); 56 map[i*m+j].push_back((i-1)*m+j); 57 } 58 if(j+1<=m&&!visited[i][j+1]) { 59 map[(i-1)*m+j].push_back((i-1)*m+j+1); 60 map[(i-1)*m+j+1].push_back((i-1)*m+j); 61 } 62 } 63 } 64 int ans=MaxMatch(); 65 printf("%d\n",ans/2); 66 for(int i=1; i<=n*m; i++) { 67 if(ly[i]!=-1&&ly[ly[i]]!=-1) { 68 int y1=i%m; 69 if(y1==0)y1=m; 70 int x1=(i-y1)/m+1; 71 int y2=ly[i]%m; 72 if(y2==0)y2=m; 73 int x2=(ly[i]-y2)/m+1; 74 ly[i]=ly[ly[i]]=-1; 75 printf("(%d,%d)--(%d,%d)\n",x1,y1,x2,y2); 76 } 77 } 78 puts(""); 79 } 80 return 0; 81 }