Get Luffy Out *

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 978    Accepted Submission(s): 426

Problem Description

Ratish is a young man who always dreams of being a hero. One day his friend Luffy was caught by Pirate Arlong. Ratish set off at once to Arlong's island. When he got there, he found the secret place where his friend was kept, but he could not go straight in. He saw a large door in front of him and two locks in the door. Beside the large door, he found a strange rock, on which there were some odd words. The sentences were encrypted. But that was easy for Ratish, an amateur cryptographer. After decrypting all the sentences, Ratish knew the following facts:

Behind the large door, there is a nesting prison, which consists of M floors. Each floor except the deepest one has a door leading to the next floor, and there are two locks in each of these doors. Ratish can pass through a door if he opens either of the two locks in it. There are 2N different types of locks in all. The same type of locks may appear in different doors, and a door may have two locks of the same type. There is only one key that can unlock one type of lock, so there are 2N keys for all the 2N types of locks. These 2N keys were made N pairs,one key may be appear in some pairs, and once one key in a pair is used, the other key will disappear and never show up again.

Later, Ratish found N pairs of keys under the rock and a piece of paper recording exactly what kinds of locks are in the M doors. But Ratish doesn't know which floor Luffy is held, so he has to open as many doors as possible. Can you help him to choose N keys to open the maximum number of doors?

 

Input

There are several test cases. Every test case starts with a line containing two positive integers N (1 <= N <= 2^10) and M (1 <= M <= 2^11) separated by a space, the first integer represents the number of types of keys and the second integer represents the number of doors. The 2N keys are numbered 0, 1, 2, ..., 2N - 1. Each of the following N lines contains two integers, which are the numbers of two keys in a pair. After that, each of the following M lines contains two integers, which are the numbers of two keys corresponding to the two locks in a door. You should note that the doors are given in the same order that Ratish will meet. A test case with N = M = 0 ends the input, and should not be processed.
 

Output

For each test case, output one line containing an integer, which is the maximum number of doors Ratish can open.
 

Sample Input

3 6
0 3
1 2
4 5
0 1
0 2
4 1
4 2
3 5
2 2
0 0
 

Sample Output

4

Hint

题目有更改!

 

Source

 
二分能够到达的层数。
首先每队钥匙之间建边。
然后前deep层的锁建边。
2-SAT判定是否可行。
 //2017-08-28
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath> using namespace std; const int N = ;
const int M = N*N*;
int head[N], rhead[N], tot, rtot;
struct Edge{
int to, next;
}edge[M], redge[M]; void init(){
tot = ;
rtot = ;
memset(head, -, sizeof(head));
memset(rhead, -, sizeof(rhead));
} void add_edge(int u, int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++; redge[rtot].to = u;
redge[rtot].next = rhead[v];
rhead[v] = rtot++;
} vector<int> vs;//后序遍历顺序的顶点列表
bool vis[N];
int cmp[N];//所属强连通分量的拓扑序 //input: u 顶点
//output: vs 后序遍历顺序的顶点列表
void dfs(int u){
vis[u] = true;
for(int i = head[u]; i != -; i = edge[i].next){
int v = edge[i].to;
if(!vis[v])
dfs(v);
}
vs.push_back(u);
} //input: u 顶点编号; k 拓扑序号
//output: cmp[] 强连通分量拓扑序
void rdfs(int u, int k){
vis[u] = true;
cmp[u] = k;
for(int i = rhead[u]; i != -; i = redge[i].next){
int v = redge[i].to;
if(!vis[v])
rdfs(v, k);
}
} //Strongly Connected Component 强连通分量
//input: n 顶点个数
//output: k 强连通分量数;
int scc(int n){
memset(vis, , sizeof(vis));
vs.clear();
for(int u = ; u < n; u++)
if(!vis[u])
dfs(u);
int k = ;
memset(vis, , sizeof(vis));
for(int i = vs.size()-; i >= ; i--)
if(!vis[vs[i]])
rdfs(vs[i], k++);
return k;
} int n, m;
pair<int, int> key[N], lock[N]; //二分层数
bool check(int deep){
init();
for(int i = ; i < n; i++){
//add_edge(key[i].first, key[i].second+2*n);
add_edge(key[i].second+*n, key[i].first);// NOT v -> u
//add_edge(key[i].second, key[i].first+2*n);
add_edge(key[i].first+*n, key[i].second);// NOT u -> v
}
for(int i = ; i < deep; i++){
add_edge(lock[i].first, lock[i].second+*n);// u -> NOT v
//add_edge(lock[i].second+2*n, lock[i].first);
add_edge(lock[i].second, lock[i].first+*n);// v -> NOT u
//add_edge(lock[i].first+2*n, lock[i].second);
}
scc(*n);
for(int i = ; i < *n; i++){
if(cmp[i] == cmp[i+*n])
return false;
}
return true;
} int main()
{
std::ios::sync_with_stdio(false);
//freopen("inputF.txt", "r", stdin);
while(cin>>n>>m){
if(!n && !m)break;
for(int i = ; i < n; i++)
cin>>key[i].first>>key[i].second;
for(int i = ; i < m; i++)
cin>>lock[i].first>>lock[i].second;
int l = , r = m, mid, ans = ;
while(l <= r){
mid = (l+r)/;
if(check(mid)){
ans = mid;
l = mid+;
}else
r = mid-;
}
cout<<ans<<endl;
}
return ;
}

HDU1816(二分+2-SAT)的更多相关文章

  1. hdu1816 + POJ 2723开锁(二分+2sat)

    题意:      有m层门,我们在最外层,我们要一层一层的进,每一层上有两把锁,我们只要开启其中的一把们就会开,我们有n组钥匙,每组两把,我们只能用其中的一把,用完后第二把瞬间就会消失,问你最多能开到 ...

  2. 证明与计算(3): 二分决策图(Binary Decision Diagram, BDD)

    0x01 布尔代数(Boolean algebra) 大名鼎鼎鼎的stephen wolfram在2015年的时候写了一篇介绍George Boole的文章:George Boole: A 200-Y ...

  3. Map Labeler POJ - 2296(2 - sat 具体关系建边)

    题意: 给出n个点  让求这n个点所能建成的正方形的最大边长,要求不覆盖,且这n个点在正方形上或下边的中点位置 解析: 当然是二分,但建图就有点还行..比较难想..行吧...我太垃圾... 2 - s ...

  4. LA 3211 飞机调度(2—SAT)

    https://vjudge.net/problem/UVALive-3211 题意: 有n架飞机需要着陆,每架飞机都可以选择“早着陆”和“晚着陆”两种方式之一,且必须选择一种,第i架飞机的早着陆时间 ...

  5. UVALive - 3211 (2-SAT + 二分)

    layout: post title: 训练指南 UVALive - 3211 (2-SAT + 二分) author: "luowentaoaa" catalog: true m ...

  6. hdu3715 2-sat+二分

    Go Deeper 题意:确定一个0/1数组(size:n)使得满足最多的条件数.条件在数组a,b,c给出. 吐槽:哎,一水提,还搞了很久!关键是抽象出题目模型(如上的一句话).以后做二sat:有哪些 ...

  7. POJ 2749 2SAT判定+二分

    题意:图上n个点,使每个点都与俩个中转点的其中一个相连(二选一,典型2-sat),并使任意两点最大 距离最小(最大最小,2分答案),有些点相互hata,不能选同一个中转点,有些点相互LOVE,必需选相 ...

  8. 2 - sat 模板(自用)

    2-sat一个变量两种状态符合条件的状态建边找强连通,两两成立1 - n 为第一状态(n + 1) - (n + n) 为第二状态 例题模板 链接一  POJ 3207 Ikki's Story IV ...

  9. BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 8748  Solved: 3835[Submi ...

随机推荐

  1. 浅谈getResource方法

    项目经常会读取一些配置文件, 因此getResource方法便能够起到重要作用 使用时主要是两种方法, 一个是字节码文件Class类, 另一个是ClassLoader类加载器 使用Class类时有两种 ...

  2. 伪装为 吃鸡账号获取器 的QQ木马分析

    本文作者:i春秋作家坏猫叔叔 0×01 起因随着吃鸡热潮的来临,各种各样的吃鸡辅助和账号交易也在互联网的灰色地带迅速繁殖滋生.其中有真有假,也不乏心怀鬼胎的“放马人”.吃过晚饭后在一个论坛看到了这样一 ...

  3. 一步步Cobol 400上手自学入门教程04 - 过程部

    过程部的作用:编写程序要执行的语句,是程序的核心. 结构: 基本语句 INITIALIZE 设置数据项的初始值 ACCEPT 接收从键盘或指定设备上获得输入数据. 例子: 当批处理文件读到调用ACCP ...

  4. 关于a标签的onclick与href的执行顺序

    onclick的事件被先执行,其次是href中定义的(页面跳转或者javascript), 同时存在两个定义的时候(onclick与href都定义了),如果想阻止href的动作,在onclick必须加 ...

  5. jdk1.8一键安装脚本(linux环境)

    1.下载jdk安装包和安装脚本 下载地址:https://pan.baidu.com/s/1bo6ADQ3 其中包括: jdk安装包:jdk-8u151-linux-x64.tar.gz jdk一键安 ...

  6. [Umbraco] document type里的父节点与子节点的设置

    虽然我们不能像做数据库设计那样建立主外键关系.但我们建立xml里父子关系,父子关系其实是指是否允许在一个页面(如频道,分类,栏目等)下创建子页面,这就相当于建立站点的树状结构,对于筛选数据会有很大的作 ...

  7. Git for Windows之分支管理、分支合并、解决分支冲突

    分支是在稳定版本出现bug的情况下,通过分支技术,在保证稳定版本稳定的情况,修改稳定版本的(差异下载的,速度极快,不同于SVN等技术,会将所有的代码下载到本地)副本,通过合并,解决冲突,最后回归到稳定 ...

  8. Python Mock的入门学习

    一.Mock是什么 Mock这个词在英语中有模拟的这个意思,因此我们可以猜测出这个库的主要功能是模拟一些东西.准确的说,Mock是Python中一个用于支持单元测试的库,它的主要功能是使用mock对象 ...

  9. editplus tag

    #T=HTML<!DOCTYPE html><html lang="zh-CN"><head><meta content="te ...

  10. [原] ubuntu 13.10 安装 winqq2013

    安装及下载地址:http://www.longene.org/forum/viewtopic.php?t=4700 ubuntu 13.10 64位系统安装后无法启动qq,因为缺少程序包.解决方案: ...