hdu 1507 二分匹配

很明显的二分匹配,只是直接把可以组成的两个正方形的地方连边的话会重复计算,结果是最大匹配数的两倍,但方案不好输出

但由于每两个相邻的正方形的(x+y)奇偶性(行和列相加)是不同的,所以,就可以把奇的放左边偶的放右边(或倒过来,都可以)

匈牙利之后直接输出匹配数和方案就好了

View Code
 1 #include<stdio.h>
2 #include<string.h>
3 #include<vector>
4 using namespace std;
5 bool map[110*110];
6 vector<int> g[10005];
7 int match[10005];
8 bool vis[10005];
9 bool dfs(int u){
10 int i;
11 for(i=0;i<g[u].size();i++){
12 int v=g[u][i];
13 if(vis[v]) continue;
14 vis[v]=true;
15 if(match[v]==-1||dfs(match[v])){
16 match[v]=u;
17 return true;
18 }
19 }
20 return false;
21 }
22 int main()
23 {
24 int n,m,i,j,k,ans,x,y;
25 while(scanf("%d%d",&n,&m),(n+m)){
26 memset(map,true,sizeof(map));
27 scanf("%d",&k);
28 for(i=1;i<=k;i++){
29 scanf("%d%d",&x,&y);
30 map[(x-1)*m+y]=false;
31 }
32 for(i=1;i<=n*m;i++)
33 g[i].clear();
34 for(i=1;i<=n*m;i++){
35 if(map[i]){
36 x=i/m;
37 y=i%m;
38 if(y==0) y=m;
39 else x+=1;
40 if((x+y)%2==0) continue;
41 if(x+1<=n&&map[i+m])
42 g[i].push_back(i+m);
43 if(x-1>=1&&map[i-m])
44 g[i].push_back(i-m);
45 if(y+1<=m&&map[i+1])
46 g[i].push_back(i+1);
47 if(y-1>=1&&map[i-1])
48 g[i].push_back(i-1);
49 }
50 }
51 ans=0;
52 memset(match,-1,sizeof(match));
53 for(i=1;i<=n*m;i++)
54 if(g[i].size()>0) {
55 memset(vis,0,sizeof(vis));
56 if(dfs(i))
57 ans++;
58 }
59 printf("%d\n",ans);
60 for(i=1;i<=n*m;i++)
61 {
62 if(map[i]&&match[i]!=-1)
63 {
64 x=i/m; y=i%m;
65 if(y==0) y=m;else x+=1;
66 int mx=match[i]/m,my=match[i]%m;
67 if(my==0) my=m;else mx+=1;
68 printf("(%d,%d)--(%d,%d)\n",x,y,mx,my);
69 }
70 }
71 printf("\n");
72 }
73 return 0;
74 }



你可能感兴趣的:(HDU)