HDU1281 棋盘游戏

  行和列构成二分图,对于某个位置[x, y],如果可以放“车”,那么行x和列y连一条有向线 x -> y (g[x][y] = 1),在进行二分图匹配的时候,如果该某位置的连线算入了最大匹配中,根据最大匹配的定义知该位置所在的行和列肯定被屏蔽掉(不会进入最大匹配中)。那么有:

  能放的棋子数 L 即为最大匹配;而要计算某个点是否为重要点,只需要将该点连线去掉,计算最大匹配,如果此时计算得到的最大匹配小于原最大匹配,那么该点为重要点,这是我们枚举所有可放棋子点即可。

View Code
 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <map>
 4 using namespace std;
 5 
 6 const int maxn = 100 + 5;
 7 
 8 int n, m, k;
 9 bool g[maxn][maxn];
10 bool vis[maxn];
11 int link[maxn];
12 int X[maxn * maxn], Y[maxn * maxn];
13 
14 bool find(int i)
15 {
16     for(int j = 1; j <= m; j ++)
17     {
18         if(g[i][j] && !vis[j])
19         {
20             vis[j] = true;
21             if(!link[j] || find(link[j]))
22             {
23                 link[j] = i;
24                 return true;
25             }
26         }
27     }
28     return false;
29 }
30 
31 int main()
32 {
33     int x, y, t = 1;
34     while(scanf("%d%d%d", &n, &m, &k) == 3)
35     {
36         memset(g, 0, sizeof g);
37         for(int i = 0; i < k; i ++)
38         {
39             scanf("%d%d", &x, &y);
40             g[x][y] = true;
41             X[i] = x, Y[i] = y;
42         }
43         memset(link, 0, sizeof link);
44         int res = 0;
45         for(int i = 1; i <= n; i ++)
46         {
47             memset(vis, false, sizeof vis);
48             res += find(i);
49         }
50         int cnt = 0;
51         for(int i = 0; i < k; i ++)
52         {
53             g[X[i]][Y[i]] = false;
54             memset(link, 0, sizeof link);
55             int tmp = 0;
56             for(int j = 1; j <= n; j ++)
57             {
58                 memset(vis, false, sizeof vis);
59                 tmp += find(j);
60             }
61             g[X[i]][Y[i]] = true;
62             cnt += (tmp < res);
63         }
64         printf("Board %d have %d important blanks for %d chessmen.\n", t++, cnt, res);
65     }
66     return 0;
67 }
原文地址:https://www.cnblogs.com/huangfeihome/p/2862671.html