Get Luffy Out *

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

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
 
 
 
经典two-sat 加 2分 。 
构图的时候要有点技巧 。。 
我是用反向构边的 。
对于条件1 ,构一条 2*u - 2*v  的无向边表示 2*u ,  2*v  不能共存
对于二分出来的深度  构一条  2*u^1  -  2*v^1  的无向边表示   2*u , 2*v 至少有一个存在
 
然后邻接链表的空间开成N*N 比较安全 , N 要开得大一点 , 不然很容易报WA ~
 
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
using namespace std;
const int N = (<<); int n , m , st[N<<] ,top;
int eh[N] , et[N*N] , nxt[N*N] , tot ;
bool mark[N<<]; struct node
{
int x , y ;
} key[N<<] , door[N<<]; void init()
{
tot = ;
memset( eh , - , sizeof eh );
memset( mark ,false , sizeof mark );
} void addedge( int u , int v )
{
et[tot] = v , nxt[tot] = eh[u] , eh[u] = tot++ ;
et[tot] = u , nxt[tot] = eh[v] , eh[v] = tot++ ;
} bool dfs( int u )
{
if( mark[u] ) return true;
if( mark[u^] ) return false ;
mark[u] = true ;
st[top++] = u ;
for( int i = eh[u] ; ~i ; i = nxt[i] ){
int v = et[i];
if( !dfs(v^) ) return false;
}
return true;
} bool solve()
{
for( int i = ; i < * n ; i += ){
if( !mark[i] && !mark[i+] ){
top = ;
if( !dfs(i) ){
while( top > ) mark[ st[--top] ] = false ;
if( !dfs(i+) ) return false;
}
}
}
return true;
} bool test( int dep )
{
init();
for( int i = ; i < n ; ++i ){
addedge( *key[i].x , *key[i].y );
}
for( int i = ; i < dep ; ++i ){
addedge(*door[i].x^,*door[i].y^);
}
return solve();
} void run()
{
int x , y ;
// cout << N <<endl;
for( int i = ; i < n ; ++i ){
scanf("%d%d",&key[i].x,&key[i].y);
} for( int i = ; i < m ; ++i ){
scanf("%d%d",&door[i].x,&door[i].y);
} int l = , r = m , ans = ;
while( l <= r )
{
int mid = ( l+r )>>;
if( test(mid) ) ans = mid , l = mid + ;
else r = mid - ;
}
printf("%d\n",ans);
} int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif // LOCAL
while( scanf("%d%d",&n,&m) ){
if( !n && !m ) break;
run();
}
}

HDU 1816 Get Luffy Out *的更多相关文章

  1. HDU - 1816 Get Luffy Out *(二分 + 2-SAT)

    题目大意:有N串钥匙,M对锁.每串钥匙仅仅能选择当中一把.怎样选择,才干使开的锁达到最大(锁仅仅能按顺序一对一对开.仅仅要开了当中一个锁就可以) 解题思路:这题跟HDU - 3715 Go Deepe ...

  2. POJ 2723 HDU 1816 Get Luffy Out

    二分答案 + 2-SAT验证 #include<cstdio> #include<cstring> #include<cmath> #include<stac ...

  3. HDU 1816, POJ 2723 Get Luffy Out(2-sat)

    HDU 1816, POJ 2723 Get Luffy Out pid=1816" target="_blank" style="">题目链接 ...

  4. Get Luffy Out * HDU - 1816(2 - sat 妈的 智障)

    题意: 英语限制了我的行动力....就是两个钥匙不能同时用,两个锁至少开一个 建个图 二分就好了...emm....dfs  开头low 写成sccno  然后生活失去希望... #include & ...

  5. hdu 1816(二分+2-sat)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1816 思路:首先将每把钥匙i拆成两个点i和i+2n,分别表示选与不选,对于被分成n对的钥匙,由于只能选 ...

  6. 【图论】2-sat总结

    2-sat总结 2-sat问题,一般表现的形式为.每一个点有两种方式a,b,要么选a,要么选b.而且点点之间有一些约束关系.比如:u和v至少一个选a.那么这就是一个表达式.把a当成真,b当成假,那就是 ...

  7. 【转载】图论 500题——主要为hdu/poj/zoj

    转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并 ...

  8. hdu图论题目分类

    =============================以下是最小生成树+并查集====================================== [HDU] 1213 How Many ...

  9. HDU图论题单

    =============================以下是最小生成树+并查集====================================== [HDU] 1213 How Many ...

随机推荐

  1. kafaka环境搭建

    激动无比,终于成功搭建了一套集群的kafka,记录下我的搭建步骤,供大家参考,如有不对,请指正: 1.集群搭建 首先搭建一个一主三从(或一主两从)的集群, 2.配置jdk环境 需要是jdk8的包 我的 ...

  2. Redis在windows下的环境搭建

    Redis在windows下的环境搭建 下载windows版本redis,,官方下载地址:http://redis.io/download, 不过官方没有Windows版本,官网只提供linux版本的 ...

  3. Windows server 2012/2016系统安装zabbix3.2客户端

    一.       上传zabbix客户端文件 将zabbix_agents_3.2.0.win.zip文件上传至服务器的指定路径. 二.       解压并修改相关信息 解压已上传的客户端文件,在co ...

  4. JAVA- 内部类及匿名内部类

    普通类,我们平时见到的那种类,就是一个后缀为.java的文件中,直接定义的类,比如 public Cat{ private String name; private int age; } 内部类, 内 ...

  5. wait()和sleep()、sleep()和yield()的区别

    wait()和sleep()的区别主要表现在一下几个方面: 原理不同.sleep()方法是Thread类的静态方法,是线程用来控制自身流程的.它会使线程暂停执行一段时间,把执行机会让给其他线程,等到时 ...

  6. chrome插件研发手册

    chrome插件研发手册 一:需求前景 对于研发的小伙伴来说,总会遇到这样的需求,想要通过代码操作已有网站的行为动作,如:自动填充表格内容(表单内容太多,想一键将表单内容填充):自动登录网站(网站登录 ...

  7. reids 持久化

    RDB: RDB是整个内存压缩过的Snapshot,RDB 的数据结构,可以配置符合的快照触发条件,默认如下 900s  1次修改 300s 10次修改 60s 10000 次修改 自动备份为dump ...

  8. oracle-SQL语句执行原理和完整过程详解

    SQL语句执行过程详解 一条sql,plsql的执行到底是怎样执行的呢? 一.SQL语句执行原理 第一步:客户端吧语句发个服务端执行 当我们在客户端执行select语句时,客户端会把这条SQL语句发送 ...

  9. 接口需要上一个接口的返回值(unittest)

    import unittest,requests ''' 使用unittest框架的时候,这个接口需要上一个接口的返回值 ''' class Test_case(unittest.TestCase): ...

  10. 【leetcode】436. Find Right Interval

    题目如下: 解题思路:题目要求的是对于任意一个区间i,要找出一个区间j,使得j的起点最接近i的终点.既然这样,我们可以把所有区间的终点组成一个列表,并按大小排序,使用二分查找就可以快速找到j区间.注意 ...