给你一个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...

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <set>
using namespace std; #define ll long long
#define inf 0x3f3f3f3f
#define eps 1e-8
#define maxn 180000
#define maxm 360000 int vv[maxm],nxt[maxm];
int head[maxn],E;
void init(){memset(head,-,sizeof(head));E=;}
void addedge(int u,int v){
vv[E]=v,nxt[E]=head[u],head[u]=E++;
}
int pre[maxn];
int vis[maxn];
bool match(int x,int n,int ID){
for(int i=head[x];i!=-;i=nxt[i]){
int v = vv[i]-n;
if(vis[v]==ID)continue;
vis[v] = ID;
if(pre[v]==- || match(pre[v],n,ID)){
pre[v]=x;
return true;
}
}
return false;
}
bool hungary(int n){
memset(pre,-,sizeof(pre));
memset(vis,,sizeof(vis));
for(int i=;i<=n;++i)
if(match(i,n,i)==false)return false;
return true;
} char ch[][];
int idx[][];
int bx[maxn],by[maxn];
int main(){
int t;
scanf("%d",&t);
while(t--){
int nn,mm;
scanf("%d%d",&nn,&mm);
memset(ch,,sizeof(ch));
for(int i=;i<=nn;++i)scanf("%s",ch[i]+);
int B=,W=;
for(int i=;i<=nn;++i)for(int j=;j<=mm;++j)
if(ch[i][j]=='B')idx[i][j]=++B,bx[B]=i,by[B]=j;
else if(ch[i][j]=='W')idx[i][j]=++W;
if(B*!=W){puts("NO");continue;}
init();
for(int b=;b<=B;++b){
int i=bx[b],j=by[b];
if(ch[i-][j]=='W')addedge(idx[i][j],B*+idx[i-][j]);
if(ch[i+][j]=='W')addedge(idx[i][j],B*+idx[i+][j]);
if(ch[i][j-]=='W')addedge(idx[i][j]+B,B*+idx[i][j-]);
if(ch[i][j+]=='W')addedge(idx[i][j]+B,B*+idx[i][j+]);
}
if(hungary(B<<))puts("YES");
else puts("NO");
}
return ;
}

UVALive 5903 Piece it together(二分图匹配)的更多相关文章

  1. UVALive 5903 Piece it together 二分匹配,拆点 难度:1

    https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_probl ...

  2. UVALive 5903 Piece it together

    一开始用的STL一直超时不能过,后来发现AC的代码基本都用的普通邻接表,然后改了一下13s,T=T,效率太低了.然后把某大神,详情戳链接http://acm.hust.edu.cn/vjudge/pr ...

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

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

  4. Tracer Deployment UVALive - 8271 二分图匹配

    复习二分图又想起了这道题,裸的二分图匹配,直接匈牙利算法就可以了,mark一下这个比较好用的稠密图匈牙利算法模板 题目:题目链接 AC代码: #include <iostream> #in ...

  5. HDU 1507 Uncle Tom's Inherited Land*(二分图匹配)

    Uncle Tom's Inherited Land* Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (J ...

  6. hdu_1045Fire Net(二分图匹配)

    hdu_1045Fire Net(二分图匹配) 标签: 图论 二分图匹配 题目链接 Fire Net Time Limit: 2000/1000 MS (Java/Others) Memory Lim ...

  7. HDU1045 Fire Net(DFS枚举||二分图匹配) 2016-07-24 13:23 99人阅读 评论(0) 收藏

    Fire Net Problem Description Suppose that we have a square city with straight streets. A map of a ci ...

  8. HDU1045:Fire Net(二分图匹配 / DFS)

    Fire Net Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  9. HDU 1045 Fire Net 【连通块的压缩 二分图匹配】

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1045 Fire Net Time Limit: 2000/1000 MS (Java/Others)    ...

随机推荐

  1. STL删除元素

    1.从vector中删除多个元素: #include <iostream> #include <vector> int main() { std::vector<int& ...

  2. lua 学习

    尽管所有的脚本语言在特定领域都有自己的一席之地,但在游戏开发的世界里,Python 和 Lua 是非常适合的,因为它们可以直接调用C++的功能. lua最让人惊喜的地方应该是它的执行速度,目前没有任何 ...

  3. Zepto.js touch模块深入分析

    目的:记录 Zepto.js touch模块 源码阅读 源码: // Zepto.js // (c) 2010-2015 Thomas Fuchs // Zepto.js may be freely ...

  4. [译]Introducing ASP.NET 5

    原文:http://weblogs.asp.net/scottgu/introducing-asp-net-5 ASP.NET 5预览版发布了, 可以在这下载最新的Visual Studio 2015 ...

  5. Hadoop! | 大数据百科 | 数据观 | 中国大数据产业观察_大数据门户

        你正在使用过时的浏览器,Amaze UI 暂不支持. 请 升级浏览器 以获得更好的体验! 深度好文丨读完此文,就知道Hadoop了! 来源:BiThink 时间:2016-04-12 15:1 ...

  6. PHP文件操作 读取与写入

    基本知识: PHP文件系统是基于Unix系统的 文件数据基本类型:二进制数据.文本数据 文件输入流:数据从源文件到内存的流动 文件输出流:数据从内存保存到文件的流动 文件操作函数: >>& ...

  7. 71-IO 流

    JAVA IO 流 一.概括 1.IO(INPUT OUTPUT)流 1.1 IO 流用来处理设备之间的数据传输 1.2JAVA 对数据的操作是通过流的方式 1.3 JAVA 用于操作流的对象都在 I ...

  8. PHP array_multisort() 函数详解 及 二维数组排序(模拟数据表记录按字段排序)

    一.先看最简单的情况. 有两个数组: $arr1 = array(1, 9, 5); $arr2 = array(6, 2, 4); array_multisort($arr1, $arr2); pr ...

  9. servlet和http请求

    1.servlet servlet是和平台无关的服务器组件,可以交互式的来浏览和修改数据,生成动态的web内容.它运行于 servlet容器中2.servlet容器 servlet容器负责servle ...

  10. CSS相邻兄弟选择器

    相邻兄弟选择器定义:选择紧接在另一个元素后的元素,而且两者有着相同的父元素. 代码一:<body> <h1>This is a heading.</h1> < ...