给你一个n*m的矩阵,每个点为'B'或'W'或'.'。然后你有一种碎片。碎片可以旋转,问可否用这种碎片精确覆盖矩阵。N,M<=500

WB  《==碎片

W

题目一看,感觉是精确覆盖(最近被覆盖洗脑了),但是仔细分析可以知道,DLX精确覆盖不是正解。因为N*M=250,000远超出DLX的可行规模(数百吧,我猜)。

然后感觉是贪心或者是抑或的什么的。。。。

看了别人的代码,发现是最大匹配。。。然后就想。。。。对哦=。=其实黑点连2个白点就是匹配呀。。。。

不得不说网络流构图还是挺有趣的,如果你会构的话。。。。

首先,如果NB*2!=NW,那必然是NO,此处特判。

构图是这样,每个黑点拆分成2个,一个只连接左右邻接的白点,一个只连接上下邻接的白点。然后就匹配了=。=

规模分析:250,000/3*2=166,666个黑点(黑点拆分翻倍),250,000/3*2=166,666个白点。边有166,666*2=333,332条。。

一开始写完这题是TLE...然后改了5处从>30sec变成100ms,还是有点收获的。。。

①如果某一个黑点匹配的那个match返回0而不是1,说明有黑点没匹配到,可直接break;结果为NO。。。。>30sec ==> 27sec,TLE==>AC

②将maxn的500,000改成180,000,快了不少。。几秒吧。。。原因应该是多case的mesmet head

③将2个for找B字符改成统计时存B字符位置。。也快了些。

④将加边的顺序改成先加左(上)边的边,再加右(下)边的边。。这个从17sec变成了3sec。。。

⑤将二分匹配的vis改成int,避免多次memset。。这个从3sec变成了100ms。。。

第一点显然的剪枝,不说了。二三点好像快得也不是特别明显,不说了。

第四点,假设某行某段是WBW,那先加左边,再加右边的结果是B->W2->W1,也就是优先右边。。。这样的话,

如果某行某段是 BWBWBWBWBWBW,那匹配的时候,每个B都只需要匹配一个就成功,不需要回溯。。。。这个的前提是顺序匹配,即从1~2B

反之,如果先加右边,再加左边的结果是B->W1->W2,也就是优先左边。。。那样的话就要回溯多次(因为还有列的影响)。。但如果是逆序匹配,即从2B~1,速度还是几秒

第五点。。。应该是最有力的改进了。。。。传统的二分匹配的vis是bool,然后匹配前memset。。因为那些点一般是数百。。。

但是我们可以把vis改成int,匹配的时候把if(vis[v])continue;改成if(vis[v]==ID)continue;

二分图最大匹配当时学得不够深入啊╮(╯▽╰)╭。。。。今天学习了。。。。第四点是SF发现的。。。第五点是参考LC他们的。。。感谢SF陪我刷了一两页的AC...

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <string>
 7 #include <vector>
 8 #include <queue>
 9 #include <set>
10 using namespace std;
11
12 #define ll long long
13 #define inf 0x3f3f3f3f
14 #define eps 1e-8
15 #define maxn 180000
16 #define maxm 360000
17
18 int vv[maxm],nxt[maxm];
19 int head[maxn],E;
20 void init(){memset(head,-1,sizeof(head));E=0;}
21 void addedge(int u,int v){
22     vv[E]=v,nxt[E]=head[u],head[u]=E++;
23 }
24 int pre[maxn];
25 int vis[maxn];
26 bool match(int x,int n,int ID){
27     for(int i=head[x];i!=-1;i=nxt[i]){
28         int v = vv[i]-n;
29         if(vis[v]==ID)continue;
30         vis[v] = ID;
31         if(pre[v]==-1 || match(pre[v],n,ID)){
32             pre[v]=x;
33             return true;
34         }
35     }
36     return false;
37 }
38 bool hungary(int n){
39     memset(pre,-1,sizeof(pre));
40     memset(vis,0,sizeof(vis));
41     for(int i=1;i<=n;++i)
42         if(match(i,n,i)==false)return false;
43     return true;
44 }
45
46 char ch[555][555];
47 int idx[555][555];
48 int bx[maxn],by[maxn];
49 int main(){
50     int t;
51     scanf("%d",&t);
52     while(t--){
53         int nn,mm;
54         scanf("%d%d",&nn,&mm);
55         memset(ch,0,sizeof(ch));
56         for(int i=1;i<=nn;++i)scanf("%s",ch[i]+1);
57         int B=0,W=0;
58         for(int i=1;i<=nn;++i)for(int j=1;j<=mm;++j)
59             if(ch[i][j]=='B')idx[i][j]=++B,bx[B]=i,by[B]=j;
60             else if(ch[i][j]=='W')idx[i][j]=++W;
61         if(B*2!=W){puts("NO");continue;}
62         init();
63         for(int b=1;b<=B;++b){
64             int i=bx[b],j=by[b];
65             if(ch[i-1][j]=='W')addedge(idx[i][j],B*2+idx[i-1][j]);
66             if(ch[i+1][j]=='W')addedge(idx[i][j],B*2+idx[i+1][j]);
67             if(ch[i][j-1]=='W')addedge(idx[i][j]+B,B*2+idx[i][j-1]);
68             if(ch[i][j+1]=='W')addedge(idx[i][j]+B,B*2+idx[i][j+1]);
69         }
70         if(hungary(B<<1))puts("YES");
71         else puts("NO");
72     }
73     return 0;
74 }

View Code

转载于:https://www.cnblogs.com/nextbin/p/3706021.html

UVALive 5903 Piece it together(二分图匹配)相关推荐

  1. 训练指南 UVALive - 4043(二分图匹配 + KM算法)

    layout: post title: 训练指南 UVALive - 4043(二分图匹配 + KM算法) author: "luowentaoaa" catalog: true ...

  2. Dinic二分图匹配 || Luogu P3386

    题面:[模板]二分图匹配 思路:Dinic实现二分图匹配,要建一个超级源点(S)和超级汇点(T),分别定为N+M+1和N+M+2 然后S去和N中的数建正边和反边,正边权值为1,反边权值为0:M中的数去 ...

  3. 二分图匹配匈牙利算法DFS实现

    1 /*==================================================*\ 2 | 二分图匹配(匈牙利算法DFS 实现) 3 | INIT: g[][]邻接矩阵; ...

  4. poj1274(二分图匹配)

    (一道基础的二分图匹配) 题目意思大概为N个牛和M个栅栏,一个牛和一个栅栏只能匹配一次,求最大匹配 直接套用二分图最大匹配模板即可 #include <iostream> #include ...

  5. poj2724(二分图匹配)

    题目大概意思为有部分奶酪需要处理,若两个奶酪的二进制只有一位不同,则可以一起处理,问最少需要处理几次 题目思路: 将可以一起处理的两个奶酪用边连接在一起,相当于边只连接二进制中有偶数个1的奶酪和二进制 ...

  6. 算法模板——二分图匹配

    实现功能为二分图匹配 原理:匈牙利算法,核心思想--匹配上了就配,没直接匹配上也要通过前面的腾出位置让这个匹配上(详见:趣写算法系列之--匈牙利算法) 本程序以Codevs2776为例 详见Codev ...

  7. 算法:ACM二分图匹配 HDU2063

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2063 摘录于互联网,原创作者redraiment,很详细的二分图匹配入门资料! 2063 过山车 Pr ...

  8. BZOJ1433 [ZJOI2009]假期的宿舍 - 二分图匹配

    题解 一道裸的二分图匹配,稍微有一点细节需要注意, 但是非常裸= = 本校并且住校的向自己的床和 自己认识的并且本校的人的床连边 离校的不需要向外连边 不是本校的就和自己认识的 并且是本校的人的床连边 ...

  9. POJ2536 二分图匹配

    题意:      有n只老鼠,m个洞,每个洞最多可以藏一只老鼠,每个老鼠的移动速度都是v,给你他们的当前坐标,和洞的坐标,突然老鹰来了,他们必须在s秒内跑到一个洞藏起来,问你最少有多少只老鼠被抓走了. ...

最新文章

  1. 四:(之六_镜像发布)Dockerfile语法梳理和实践
  2. css 识别变量中的换行符_Python编程 第二章——变量和简单数据类型
  3. [crypto]-02-非对称加解密RSA原理概念详解
  4. JAVA 通过URL 获取页面内容
  5. Mybatis if test 中int integer判断非空的坑
  6. ORA-00600[kjpsod1]ORA-44203错误一例
  7. “没有找到iliertutil.dll,因此这个应用程序未能启动。”文件拷贝 PE 或者 dos...
  8. SQL入侵恢复XP_CMDSHLL与开3389
  9. 大型项目使用Automake/Autoconf完成编译配置
  10. IOS – OpenGL ES 调节图像单色 GPUImageMonochromeFilter
  11. 1-10:学习shell之进程
  12. php程序控制结构,PHP 控制结构
  13. zTree加Layui 实现增加和删除,有子节点不允许删除
  14. 小程序资源服务器,开发小程序没有服务器资源
  15. Alpha冲刺(2/10)——2019.4.24
  16. 使用vue写扫雷游戏
  17. Meinheld 和 Gevent_XYM
  18. PYTHON_错误处理
  19. kaggle比赛_有关kaggle比赛里的shake up分析
  20. 如何将html转换成url,HTML URL

热门文章

  1. ab st语言编程手册_木兰编程语言 0.0.14.7:功能覆盖初版用户手册;Gitee Go 流水线尝鲜...
  2. 奥托尼克斯接近开关型号_萨科微SLKOR的MOS 场效应管应用范围和型号
  3. 前端和后端哪个工资高_前端、后端、全栈都是干嘛的?哪个薪资高?
  4. 最小树形图+朱刘算法
  5. linux系统下tar/gz/7z/xz/bz2/zip等各种格式的打包压缩解压
  6. 使用doxygen和latex生成PDF文件
  7. 广东省那么发达,为什么还有全国贫困县?
  8. 老赖整治升级,不还钱直接扣微信钱包!
  9. 这些明星日入斗金,为什么还要贷款?
  10. JUNOS Olive GRE Tunnel Configuration