HDU 1281解题报告
来源:互联网 发布:家庭千兆网络组建方案 编辑:程序博客网 时间:2024/05/16 10:02
棋盘游戏
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 2651 Accepted Submission(s): 1547
所以现在Gardon想让小希来解决一个更难的问题,在保证尽量多的“车”的前提下,棋盘里有些格子是可以避开的,也就是说,不在这些格子上放车,也可以保证尽量多的“车”被放下。但是某些格子若不放子,就无法保证放尽量多的“车”,这样的格子被称做重要点。Gardon想让小希算出有多少个这样的重要点,你能解决这个问题么?
第一行有三个数N、M、K(1<N,M<=100 1<K<=N*M),表示了棋盘的高、宽,以及可以放“车”的格子数目。接下来的K行描述了所有格子的信息:每行两个数X和Y,表示了这个格子在棋盘中的位置。
Board T have C important blanks for L chessmen.
3 3 41 21 32 12 23 3 41 21 32 13 2
Board 1 have 0 important blanks for 2 chessmen.Board 2 have 3 important blanks for 3 chessmen.
这道题比较坑,也比较难。题目中的重点边的定义也不甚清晰,可能让人难以理解出题人的意思。
下面引用别人对本题的解读,我觉得本题还是属于比较难的题目。
这题可以看成行与列的二分匹配问题,因为每行每列至多只能放一个棋子。第i行与j列匹配代表棋盘第i行j列这个位置放棋子。那么,棋盘上的点就是二分图的边;“车”的个数就是二分图的最大匹配数。题目的关键是求重要点。现假设最大匹配数为ans,且已经求出某一种匹配策略。
1 :枚举所有可以放的点,去掉某一点后(这里的点指棋盘上的点,也就是二分图的边),就得到一个新的二分图了
if (新二分图的最大匹配数 == ans)
then这个点不是重要点
else // 即新的二分图达不到ans这个匹配数,那么这个点就是必须放的,否则达不到ans。-->重要边
then计数+1
2 :但是这样枚举效率太低。实际上,删边只需考虑求出的匹配边(因为删除非匹配边得到的匹配数不变)。这样,只需删除ans条边,复杂度就降低了。
再进一步分析,删除一条边以后,没有必要重新求删边后新的二分图的最大匹配,只需检查删边后的匹配中--->可不可以再找到新的增广链就可以了。这样,时间复杂度就进一步降到了。
3 : 这样的优化是不可取的:
在判断是否存在增广路得时候,不能只以删除的匹配边的顶点作起点来找增广路
正确的方法是:以删边后新的二分图的所有未匹配顶点出发做增广,都找不到增广路,匹配不能再增加
总结本题,需要对二分图最大匹配有深刻的认识。二分图最大匹配必须要重点注意的是:如果不存在增广路,即为最大匹配。删掉一条边以后,如果还能找到增广路,那么就能够达到原有的匹配数。因为找到增广路以后对增广路取反以后,边数加1。如果从剩下未匹配的边开始无法找到增广路,那么就说明删边操作后,新的二分图无法达到原有的匹配数。这是二分图最大匹配最实质性的东西。必须深入思考后才能够理解该删边操作寻找增广路做法的合理性。
下面是参考代码:
#include<cstdio>#include<iostream>#include<algorithm>#include<vector>#include<cstring>#define pb push_back#define CLR(x) memset(x,0,sizeof(x))#define __CLR(x) memset(x,-1,sizeof(x))using namespace std;int n,m,k;int mx[110],my[110];bool vis[110];int g[110][110];bool dfs(int u,bool &flag) //引入flag是为了保证在进行删边操作时不改变匹配的对应值{ for(int i=1; i<=m; i++) { if(g[u][i]&&!vis[i]) { vis[i]=1; if(my[i]==-1||dfs(my[i],flag)) { if(flag) { my[i]=u; mx[u]=i; } return true; } } } return false;}int main(){ int cas=1; while(~scanf("%d%d%d",&n,&m,&k)) { CLR(g); for(int i=1; i<=k; i++) { int x,y; scanf("%d%d",&x,&y); g[x][y]=1; } __CLR(mx); __CLR(my); int num=0; for(int i=1; i<=n; i++) { if(mx[i]==-1) { CLR(vis); bool f=true; if(dfs(i,f)) num++; } } int ans=0; for(int i=1; i<=n; i++) { if(mx[i]!=-1) //删除匹配边 { int t=mx[i]; mx[i]=-1,my[t]=-1; g[i][t]=0; bool flag=0; for(int j=1; j<=n; j++) { if(mx[j]==-1) //对未匹配点进行搜索 { CLR(vis); bool f=false; if(dfs(j,f)) { flag=1; break; } } } if(!flag) ans++; mx[i]=t; //对匹配边进行恢复 my[t]=i; g[i][t]=1; } } printf("Board %d have %d important blanks for %d chessmen.\n",cas++,ans,num); }}
- HDU 1281解题报告
- HDU 3342 解题报告
- HDU 3336 解题报告
- HDU 3335 解题报告
- hdu 2516解题报告
- hdu 1004解题报告
- hdu 2139解题报告
- hdu 1019解题报告
- hdu 1064 解题报告
- HDU 1113 解题报告
- hdu 1068 解题报告
- HDU:2050解题报告
- hdu 4001解题报告
- hdu 1005解题报告
- HDU解题报告--1003
- HDU解题报告--1004
- HDU解题报告--1005
- HDU 1005 解题报告
- POJ 题目2240 Arbitrage(最短路变形)
- POJ 1274解题报告
- 一款经典简洁的CSS滑动门代码
- Cocos2dx中新头文件无法被找到的问题
- Popular Cows - POJ 2186 Tarjan
- HDU 1281解题报告
- 互联网催生新学科-互联网神经学
- Prime Ring Problem
- Android Studio安装后Fetching android sdk component information超时的解决方案
- 基于bootstrup的jQuery超酷hero幻灯片特效
- HTML5实现Winamp2.9音频播放器插件
- HDU 2157解题报告
- pat1069 The Black Hole of Numbers
- ORACLE 10G 官方文档演示:查找手工建库语句