POJ2723-Get Luffy Out(2-SAT)

Get Luffy Out

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 7456   Accepted: 2835

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 divided into N 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 <= 210) and M (1 <= M <= 211) 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 different 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

题意:n对钥匙,m扇门,第i对钥匙表示两者不能同时选,第i扇门需要所需两个钥匙中的一个,只有开第i扇门,才能开第i+1扇门,问最多能开多少扇门。
思路:2-SAT。二分答案,根据第i对钥匙 a,b: a->b+2n, b->a+2n 对于第i扇门 所需的两把钥匙a,b: a+2n->b,b+2n->a 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
const int maxn = 1100*4;
struct ee{
    int u,v;
}ee[maxn*10];
struct edge{
    int v,nxt;
}e[maxn*maxn];
int dfs_clk,scc_cnt;
int sccno[maxn];
int lown[maxn],dfn[maxn];
int head[maxn];
stack<int> S;
int nume;
int n,m;
void init(){
    nume = 1;
    memset(dfn,0,sizeof dfn);
    memset(sccno,0,sizeof sccno);
    scc_cnt = dfs_clk = 0;
    memset(head,0,sizeof head);
    while(!S.empty()) S.pop();
}
void addedge(int u,int v){
    e[++nume].nxt = head[u];
    e[nume].v = v;
    head[u] = nume;
}
void Tarjan(int u){
    S.push(u);
    lown[u] = dfn[u] = ++dfs_clk;
    for(int i = head[u]; i; i = e[i].nxt){
        int v = e[i].v;
        if(!dfn[v]){
            Tarjan(v);
            lown[u] = min(lown[u],lown[v]);
        }
        else if(!sccno[v]){
            lown[u] = min(lown[u],dfn[v]);
        }
    }
    if(lown[u]==dfn[u]){
        scc_cnt++;
        while(true){
            int x = S.top(); S.pop();
            sccno[x] = scc_cnt;
            if(x == u) break;
        }
    }
}
bool can(int x){
    init();
    for(int i = 0; i < n; i++){
        addedge(ee[i].v,ee[i].u+2*n);
        addedge(ee[i].u,ee[i].v+2*n);
    }
    for(int i = 0; i < x; i++){
        addedge(ee[i+n].u+2*n,ee[i+n].v);
        addedge(ee[i+n].v+2*n,ee[i+n].u);
    }
    for(int i = 0; i < 4*n; i++){
        if(!dfn[i])
            Tarjan(i);
    }
    for(int i = 0; i < 2*n; i++){
        if(sccno[i]==sccno[i+2*n]) return false;
    }
    return true;
}
int binary_search(int L,int R){
    while(L <= R){
        int mid = (L+R)>>1;
        if(can(mid)){
            L = mid+1;
        }else{
            R = mid-1;
        }
    }
    return R;
}
int main(){

    while(~scanf("%d%d",&n,&m) && n+m){
        for(int i = 0; i < n; i++)
            scanf("%d%d",&ee[i].u,&ee[i].v);

        for(int i = 0; i < m; i++)
            scanf("%d%d",&ee[i+n].u,&ee[i+n].v);
        int d = binary_search(0,m);
        printf("%d\n",d);
    }
    return 0;
}

POJ2723-Get Luffy Out(2-SAT)

时间: 2024-10-10 08:49:39

POJ2723-Get Luffy Out(2-SAT)的相关文章

图论专题整理

poj1251 Jungle Roads 思路:最小生成树          解题报告Here CodeForces 472D Design Tutorial: Inverse the Problem 思路:最小生成树          解题报告Here poj1789 Truck History 思路:最小生成树          解题报告Here poj1639 Picnic Planning 思路:顶点度数限制的MST         解题报告Here poj1062 昂贵的聘礼 思路:S

LA 3211 飞机调度(2—SAT)

https://vjudge.net/problem/UVALive-3211 题意: 有n架飞机需要着陆,每架飞机都可以选择“早着陆”和“晚着陆”两种方式之一,且必须选择一种,第i架飞机的早着陆时间为E,晚着陆时间为L,不得在其他时间着陆.你的任务是为这些飞机安排着陆方式,使得整个着陆计划尽量安全.换句话说,如果把所有飞机的实际着陆时间按照从早到晚的顺序排列,相邻两个着陆时间间隔的最小值. 思路: 二分查找最大值P,每次都用2—SAT判断是否可行. 1 #include<iostream>

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个结点,但是后面发现数据有可能一把钥匙,出如今不同串(真是不合

8.3吝啬SAT问题

吝啬SAT问题是这样的:给定一组子句(每个子句都是其中文字的析取)和整数k,求一个最多有k个变量为true的满足赋值--如果该赋值存在.证明吝啬SAT是NP-完全问题. 1.易知吝啬SAT的解可以在多项式时间内验证,因此属于NP问题. 2.如果我们把吝啬SAT问题中的k设置为输入的数目,那么SAT问题就可以规约到吝啬SAT问题,所以吝啬SAT问题是np-完全问题.

POJ 3207 Ikki&#39;s Story IV - Panda&#39;s Trick(2 - sat啊)

题目链接:http://poj.org/problem?id=3207 Description liympanda, one of Ikki's friend, likes playing games with Ikki. Today after minesweeping with Ikki and winning so many times, he is tired of such easy games and wants to play another game with Ikki. liy

Get Luffy Out (poj 2723 二分+2-SAT)

Language: Default Get Luffy Out Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7969   Accepted: 3061 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 o

(2 sat) poj 2723

Get Luffy Out Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7758   Accepted: 2969 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 Arlo

多边形碰撞 -- SAT方法

检测凸多边形碰撞的一种简单的方法是SAT(Separating Axis Theorem),即分离轴定理. 原理:将多边形投影到一条向量上,看这两个多边形的投影是否重叠.如果不重叠,则认为这两个多边形是分离的,否则找下一条向量来继续投影.我们不需要比较很多条向量,因为已经在数学上证明,多边形每条边的垂直向量就是我们需要的向量. 1.AABB 让我们首先以AABB开始(AABB是一种两边分别平行于X-Y轴的矩形) 判断两个AABB是否碰撞,我们只需要投影两次,分别是投影在平行于X轴和Y轴的向量上

hdu 4751 Divide Groups 2—sat问题 还是未理解

Divide Groups Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1443    Accepted Submission(s): 512 Problem Description This year is the 60th anniversary of NJUST, and to make the celebration mor