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 }