HDU 1816 Get Luffy Out *

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

Beijing 2005

经典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 = (1<<13);

int  n , m , st[N<<1] ,top;
int eh[N] , et[N*N] , nxt[N*N] , tot ;
bool mark[N<<2];

struct node
{
    int x , y ;
}  key[N<<1] , door[N<<1];

void init()
{
    tot = 0 ;
    memset( eh , -1 , 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^1] ) return false ;
    mark[u] = true ;
    st[top++] = u ;
    for( int i = eh[u] ; ~i ; i = nxt[i] ){
        int v = et[i];
        if( !dfs(v^1) )  return false;
    }
    return true;
}

bool solve()
{
    for( int i = 0 ; i < 4 * n ; i += 2 ){
        if( !mark[i] && !mark[i+1] ){
            top = 0 ;
            if( !dfs(i) ){
                while( top > 0 ) mark[ st[--top] ] = false ;
                if( !dfs(i+1) ) return false;
            }
        }
    }
    return true;
}

bool test( int dep )
{
    init();
    for( int i = 0 ; i < n ; ++i ){
        addedge( 2*key[i].x , 2*key[i].y );
    }
    for( int i = 0 ; i < dep ; ++i ){
        addedge(2*door[i].x^1,2*door[i].y^1);
    }
    return solve();
}

void run()
{
    int x , y ;
//    cout << N <<endl;
    for( int i = 0 ; i < n ; ++i ){
        scanf("%d%d",&key[i].x,&key[i].y);
    }

    for( int i = 0 ; i < m ; ++i ){
        scanf("%d%d",&door[i].x,&door[i].y);
    }

    int l = 0 , r = m , ans = 0 ;
    while( l <= r )
    {
        int mid = ( l+r )>>1;
        if( test(mid) ) ans = mid , l = mid + 1 ;
        else r = mid - 1;
    }
    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();
    }
}
时间: 2024-11-01 17:04:09

HDU 1816 Get Luffy Out *的相关文章

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

题目大意:有N串钥匙,M对锁.每串钥匙只能选择其中一把,如何选择,才能使开的锁达到最大(锁只能按顺序一对一对开,只要开了其中一个锁即可) 解题思路:这题跟HDU - 3715 Go Deeper 这题的限制比较简单,都是二选一,2-SAT的裸题,只不过加了二分而已 附上HDU - 3715 Go Deeper题解 #include <cstdio> #include <cstring> #include <algorithm> #include <vector&g

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

HDU 1816, POJ 2723 Get Luffy Out pid=1816" target="_blank" style="">题目链接 题意:N串钥匙.每串2把,仅仅能选一把.然后有n个大门,每一个门有两个锁,开了一个就能通过,问选一些钥匙,最多能通过多少个门 思路:二分通过个数.然后对于钥匙建边至少一个不选,门建边至少一个选,然后2-sat搞一下就可以. 一開始是按每串钥匙为1个结点,但是后面发现数据有可能一把钥匙,出如今不同串(真是不合

hdu 3715 hdu 1816 hdu 4115 (2-sat)

三个2-sat问题,我总结一下自己的经验,我还是太菜,好久没做2-sat,又不太会建图了 总结:2-sat问题的核心就是建模 建模的思想很重要: 1.首先要怎么才能看出来是2-sat问题,对于每一个点,都有两种选择,则可以考虑是2-sat 比如让你在n组里面选n个,每组2个东西,这样就是2-sat的模型 2.确定是2-sat问题之后,就是要确定,拥有两种选择的对象,比如下面的例题里,有的是x[i]的取值有0或者1两种,有的是一串钥匙有两个,但你只能选择其中一个,则对于一个钥匙,它的取值有取或者不

【图论】2-sat总结

2-sat总结 2-sat问题,一般表现的形式为.每一个点有两种方式a,b,要么选a,要么选b.而且点点之间有一些约束关系.比如:u和v至少一个选a.那么这就是一个表达式.把a当成真,b当成假,那就是u真或v真.2-sat的题目就是这样.给定这些约束,推断是否会矛盾 注意表达式的转化形式,(事实上就是离散数学中那几种转换方式) 比方(u真且v真)或(u假且v假)就能够转化成(u真或v假)且(u假或v真),这样就能建立关系 2-sat中的原理,事实上和2染色是一样的,把每一个结点拆分成一个真结点和

【图论】

2-sat总结 2-sat问题,一般表现的形式为,每个点有两种方式a,b,要么选a,要么选b,并且点点之间有一些约束关系,例如:u和v至少一个选a,那么这就是一个表达式,把a当成真,b当成假,那就是u真或v真,2-sat的题目就是这样,给定这些约束,判断是否会矛盾 注意表达式的转化形式,(其实就是离散数学中那几种转换方式) 比如(u真且v真)或(u假且v假)就可以转化成(u真或v假)且(u假或v真),这样就能建立关系 2-sat中的原理,其实和2染色是一样的,把每个结点拆分成一个真结点和一个假结

图论 500题——主要为hdu/poj/zoj

转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并查集======================================[HDU]1213   How Many Tables   基础并查集★1272   小希的迷宫   基础并查集★1325&&poj1308  Is It A Tree?   基础并查集★1856   More i

hdu图论题目分类

=============================以下是最小生成树+并查集====================================== [HDU] 1213 How Many Tables 基础并查集★ 1272 小希的迷宫 基础并查集★ 1325&&poj1308 Is It A Tree? 基础并查集★ 1856 More is better 基础并查集★ 1102 Constructing Roads 基础最小生成树★ 1232 畅通工程 基础并查集★ 123

题单二:图论500

http://wenku.baidu.com/link?url=gETLFsWcgddEDRZ334EJOS7qCTab94qw5cor8Es0LINVaGMSgc9nIV-utRIDh--2UwRLvsvJ5tXFjbdpzbjygEdpGehim1i5BfzYgYWxJmu ==========  以下是最小生成树+并查集=========================[HDU]1213         How Many Tables        基础并查集★1272         小

图论五百题!

生死看淡不服就淦,这才是人生! =============================以下是最小生成树+并查集======================================[HDU]1213 How Many Tables 基础并查集★1272 小希的迷宫 基础并查集★1325&&poj1308 Is It A Tree? 基础并查集★1856 More is better 基础并查集★1102 Constructing Roads 基础最小生成树★1232 畅通工程 基