题目:http://acm.hdu.edu.cn/showproblem.php?pid=1507
题目有指出 ( (N x M) - K <= 50), 所以最多也就 50 个点. 然后遍历图上
每一个可行点点, 把它和他 上下左右的可行点连边, 最后就得到了一个二分图, 然后直接
最大匹配, 不过结果有问题, 分析不透彻, 出现了重边. 再 分析下, 因为相邻块之间的下标
和存在奇偶关系, 所以只取 偶数 或 奇数点 建图就行了.
View Code
1 #include<stdio.h>
2 #include<string.h>
3
4 #define maxn 110
5
6 struct node
7 {
8 int x,y;
9 }ans[51];
10
11 int dx[]={-1,1,0,0};
12 int dy[]={0,0,-1,1};
13
14 int n,m,cnt;
15 int a[maxn][maxn],mark[51];
16 bool hash[maxn][maxn],visit[51],map[51][51];
17
18 void get_map()
19 {
20 int i,j,k,x,y;
21 scanf("%d",&k);
22 memset(hash,0,sizeof(hash));
23 while(k--)
24 {
25 scanf("%d%d",&x,&y);
26 hash[x][y]=1;
27 }
28 cnt=1;
29 for(i=1;i<=n;i++)
30 for(j=1;j<=m;j++)
31 if(hash[i][j]==0)
32 {
33 a[i][j]=cnt;
34 ans[cnt].x=i;
35 ans[cnt].y=j;
36 cnt++;
37 }
38
39 memset(map,0,sizeof(map));
40 for(i=1;i<=n;i++)
41 for(j=1;j<=m;j++)
42 if(hash[i][j]==0)
43 {
44 for(k=0;k<4;k++)
45 {
46 x=i+dx[k];
47 y=j+dy[k];
48 if(x>=1&&x<=n&&y>=1&&y<=m&&hash[x][y]==0)
49 {
50 map[a[i][j]][a[x][y]]=1;
51 map[a[x][y]][a[i][j]]=1;
52 }
53 }
54 }
55 }
56
57 bool dfs(int k)
58 {
59 int i;
60 for(i=1;i<cnt;i++)
61 {
62 if((ans[i].x+ans[i].y)%2==1)
63 continue;
64 if(map[k][i]&&!visit[i])
65 {
66 visit[i]=1;
67 if(mark[i]==-1||dfs(mark[i]))
68 {
69 mark[i]=k;
70 return true;
71 }
72 }
73 }
74 return false;
75 }
76
77 void output()
78 {
79 int i;
80 for(i=1;i<cnt;i++)
81 {
82 if(mark[i]!=-1)
83 {
84 printf("(%d,%d)--(%d,%d)\n",ans[i].x,ans[i].y,ans[mark[i]].x,ans[mark[i]].y);
85 }
86 }
87 }
88
89 void solve()
90 {
91 int i,count=0;
92 memset(mark,-1,sizeof(mark));
93 for(i=1;i<cnt;i++)
94 {
95 if((ans[i].x+ans[i].y)%2==0)
96 continue;
97 memset(visit,0,sizeof(visit));
98 if(dfs(i))
99 count++;
100 }
101 printf("%d\n",count);
102 output();
103 printf("\n");
104 }
105
106 int main()
107 {
108 while(scanf("%d%d",&n,&m)!=EOF)
109 {
110 if(n==0&&m==0)
111 break;
112 get_map();
113 solve();
114 }
115 return 0;
116 }