HDU1281: 棋盘游戏(二分图匹配)
Posted heyuhhh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU1281: 棋盘游戏(二分图匹配)相关的知识,希望对你有一定的参考价值。
棋盘游戏
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 6897 Accepted Submission(s): 4005
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1281
Description:
小希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放尽量多的一些国际象棋里面的“车”,并且使得他们不能互相攻击,这当然很简单,但是Gardon限制了只有某些格子才可以放,小希还是很轻松的解决了这个问题(见下图)注意不能放车的地方不影响车的互相攻击。
所以现在Gardon想让小希来解决一个更难的问题,在保证尽量多的“车”的前提下,棋盘里有些格子是可以避开的,也就是说,不在这些格子上放车,也可以保证尽量多的“车”被放下。但是某些格子若不放子,就无法保证放尽量多的“车”,这样的格子被称做重要点。Gardon想让小希算出有多少个这样的重要点,你能解决这个问题么?
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.
题意:
要求放尽量多的车,问有多少个“重要点”。
题解:
“重要点”可以这样理解,首先当放了最多的车时,重要点上面有车;倘若现在把重要点关闭,那么放车的最大数量会减少。
对于非重要点而言,关闭这个点对最终结果也无影响。
放车的位置的横纵坐标可以看成一对行丶列的匹配,并且只能一一匹配,所以可以建二分图,左边集合为横坐标,右边集合为纵坐标,来进行最大的匹配。
想要判断一个点是否为重要点,可以把这个点关闭,然后再求一次最大匹配,比较两次的最大匹配数。
由于数据量较小,虽然理论上来说时间复杂度较大,但还是可以过~
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; const int N = 105; int map[N][N],check[N],match[N]; int n,m,k,ans,l,t=0; inline void init(){ memset(match,-1,sizeof(match)); memset(check,0,sizeof(check)); ans=0;l=0;memset(map,0,sizeof(map)); } inline int dfs(int x){ for(int i=1;i<=m;i++){ if(map[x][i] && !check[i]){ check[i]=1; if(match[i]==-1 || dfs(match[i])){ match[i]=x; return 1; } } } return 0; } int main(){ while(scanf("%d%d%d",&n,&m,&k)!=EOF){ init(); ++t; for(int i=1,x,y;i<=k;i++){ scanf("%d%d",&x,&y); map[x][y]=1; } for(int i=1;i<=n;i++){ memset(check,0,sizeof(check)); if(dfs(i)) ans++; } int cnt; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(map[i][j]){ map[i][j]=0;cnt=0;memset(match,-1,sizeof(match)); for(int k=1;k<=n;k++){ memset(check,0,sizeof(check)); if(dfs(k)) cnt++; } map[i][j]=1; if(cnt!=ans) l++; } } } printf("Board %d have %d important blanks for %d chessmen. ",t,l,ans); } return 0; }
以上是关于HDU1281: 棋盘游戏(二分图匹配)的主要内容,如果未能解决你的问题,请参考以下文章