HDU1281 棋盘游戏 棋盘游戏

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5344    Accepted Submission(s): 3157


Problem Description
小 希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放尽量多的一些国际象棋里面的“车”,并且使得他们不能互相攻击,这当然很简单,但是 Gardon限制了只有某些格子才可以放,小希还是很轻松的解决了这个问题(见下图)注意不能放车的地方不影响车的互相攻击。
所以现在 Gardon想让小希来解决一个更难的问题,在保证尽量多的“车”的前提下,棋盘里有些格子是可以避开的,也就是说,不在这些格子上放车,也可以保证尽量 多的“车”被放下。但是某些格子若不放子,就无法保证放尽量多的“车”,这样的格子被称做重要点。Gardon想让小希算出有多少个这样的重要点,你能解 决这个问题么?
HDU1281 棋盘游戏
棋盘游戏
 
Input
输入包含多组数据,
第一行有三个数N、M、K(1<N,M<=100 1<K<=N*M),表示了棋盘的高、宽,以及可以放“车”的格子数目。接下来的K行描述了所有格子的信息:每行两个数X和Y,表示了这个格子在棋盘中的位置。
 
Output
对输入的每组数据,按照如下格式输出:
Board T have C important blanks for L chessmen.
 
Sample Input
3 3 4 1 2 1 3 2 1 2 2 3 3 4 1 2 1 3 2 1 3 2
 
Sample Output
Board 1 have 0 important blanks for 2 chessmen. Board 2 have 3 important blanks for 3 chessmen.
 
Author
Gardon
 
Source
 
Recommend
lcy   |   We have carefully selected several similar problems for you:  1068 1151 1150 1507 1528 
 
【题解】
把(i,j)放车意味着i,j连一条边,于是就成了二分图最大匹配
关键点的话,无非就是枚举当前匹配的边删除,看能不能再找匹配
不难证明关键点一定在找到的第一个匹配上
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 
  6 inline void read(int &x)
  7 {
  8     x = 0;char ch = getchar(), c = ch;
  9     while(ch < '0' || ch > '9')c = ch, ch = getchar();
 10     while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
 11     if(c == '-')x = -x;
 12 }
 13 
 14 const int MAXN = 100 + 10;
 15 
 16 int g[MAXN][MAXN], n, m, k;
 17 
 18 int lk[MAXN],b[MAXN];
 19 
 20 int dfs(int u)
 21 {
 22     for(register int i = 1;i <= n;++ i)
 23     {
 24         if(g[u][i] && !b[i])
 25         {
 26             b[i] = 1;
 27             if(lk[i] == -1 || dfs(lk[i]))
 28             {
 29                 lk[i] = u;
 30                 return 1;
 31             }
 32         }
 33     }
 34     return 0;
 35 } 
 36 
 37 int xiongyali()
 38 {
 39     int ans = 0;
 40     memset(lk, -1, sizeof(lk));
 41     for(register int i = 1;i <= n;++ i)
 42     {
 43         memset(b, 0, sizeof(b));
 44         ans += dfs(i);
 45     }    
 46     return ans;
 47 }
 48 
 49 int lk2[MAXN],b2[MAXN];
 50 
 51 int dfs2(int u)
 52 {
 53     for(register int i = 1;i <= n;++ i)
 54     {
 55         if(g[u][i] && !b2[i])
 56         {
 57             b2[i] = 1;
 58             if(lk2[i] == -1 || dfs2(lk2[i]))
 59             {
 60                 lk2[i] = u;
 61                 return 1;
 62             }
 63         }
 64     }
 65     return 0;
 66 } 
 67 
 68 int xiongyali2()
 69 {
 70     int ans = 0;
 71     memset(lk2, -1, sizeof(lk2));
 72     for(register int i = 1;i <= n;++ i)
 73     {
 74         memset(b2, 0, sizeof(b2));
 75         ans += dfs2(i);
 76     }    
 77     return ans;
 78 }
 79 
 80 int main()
 81 {
 82     int t = 0;
 83     while(scanf("%d %d %d", &n, &m, &k) != EOF)
 84     {
 85         ++ t;
 86         memset(g, 0, sizeof(g));
 87         register int tmp1, tmp2, ans = 0;
 88         for(register int i = 1;i <= k;++ i)
 89         {
 90             read(tmp1), read(tmp2);
 91             g[tmp1][tmp2] = 1;
 92         }
 93         tmp1 = xiongyali();
 94         for(register int i = 1;i <= m;++ i)
 95         {
 96             if(lk[i] != -1)
 97             {
 98                 g[lk[i]][i] = 0;
 99                 tmp2 = xiongyali2();
100                 if(tmp2 != tmp1) ++ ans;
101                 g[lk[i]][i] = 1;
102             }
103         }
104         printf("Board %d have %d important blanks for %d chessmen.
", t, ans, tmp1);
105     }
106     return 0;
107 }
HDU1281