zoukankan      html  css  js  c++  java
  • ACM POJ 2723 Get Luffy Out(2SAT入门)

    题目链接:http://poj.org/problem?id=2723

     

    【题目大意】

    有2n把钥匙,分成2组,给你每组的钥匙信息,并且每组的钥匙只能用一个。

    有m个门,每个门有2个锁,只要打开一个锁这个门就开了。(顺序遇见m个门)

    问你最多能够打开多少个门。

    【解题思路】

    因为只能门只能按照顺序打开,所以很自然二分是个很好的选择。
    建图的依据:
    1、每对钥匙a,b有(a->!b),(b->!a)   也就是 a and b = 0 a被用b不被用,或b被用a不被用,或a,b都不被用
    2、每善门对应锁的钥匙a,b有(!a->b),(!b->a) 也就是 a or b = 1,用a能打开用b不能打开,或用b能打开用a不能打开,或用a能打开用b也能打开

    用二分法求解:

     

    我下面用了两种方法求解的,时间都差不多。也就是求解强连通分量的两种方法。

    /*
    POJ 2723 Get Luffy Out
    AC代码
    */

    #include
    <stdio.h>
    #include
    <math.h>
    #include
    <iostream>
    using namespace std;
    const int MAXN=1<<12;
    const int MAXM=1<<24;
    struct Node
    {
    int l,r;
    }e[MAXN];
    struct Node1
    {
    int from,to,next;
    }edge1[MAXM],edge2[MAXM];
    int visit1[MAXN],visit2[MAXN],head1[MAXN],head2[MAXN],Belong[MAXN],T[MAXN];
    int tol1,tol2,Bcnt,Tcnt;
    int hash[MAXN];
    void add(int a,int b)
    {
    edge1[tol1].from
    =a;edge1[tol1].to=b;edge1[tol1].next=head1[a];head1[a]=tol1++;
    edge2[tol2].from
    =b;edge2[tol2].to=a;edge2[tol2].next=head2[b];head2[b]=tol2++;
    }
    void dfs1(int x)
    {
    int j;
    visit1[x]
    =1;
    for(j=head1[x];j!=-1;j=edge1[j].next)
    if(visit1[edge1[j].to]==0) dfs1(edge1[j].to);
    T[Tcnt
    ++]=x;
    }
    void dfs2(int x)
    {
    int j;
    visit2[x]
    =1;
    Belong[x]
    =Bcnt;
    for(j=head2[x];j!=-1;j=edge2[j].next)
    if(visit2[edge2[j].to]==0) dfs2(edge2[j].to);
    }
    int main()
    {
    int i,j,n,m;
    int right,left,mid,ans;
    while(scanf("%d%d",&n,&m)!=EOF)
    {

    if(n==0&&m==0)break;
    int a,b;
    for(i=0;i<n;i++)
    {
    scanf(
    "%d%d",&a,&b);
    hash[a]
    =b;
    hash[b]
    =a;
    }
    for(i=0;i<m;i++)
    scanf(
    "%d%d",&e[i].l,&e[i].r);
    left
    =0;
    right
    =m;
    while(left<=right)
    {
    mid
    =(left+right)/2;
    for(i=0;i<4*n;i++)
    {
    head1[i]
    =-1;
    head2[i]
    =-1;
    visit1[i]
    =0;
    visit2[i]
    =0;
    }
    tol1
    =tol2=0;
    Tcnt
    =Bcnt=0;
    for(i=0;i<2*n;i++)
    {
    add(i,hash[i]
    +2*n);
    }
    for(i=0;i<mid;i++)
    {

    if(e[i].l!=e[i].r)
    {
    add(e[i].l
    +2*n,e[i].r);
    add(e[i].r
    +2*n,e[i].l);
    }
    if(e[i].l==e[i].r)
    {
    add(e[i].l
    +2*n,e[i].l);
    }

    }
    for(i=0;i<4*n;i++)
    if(!visit1[i]) dfs1(i);
    for(i=Tcnt-1;i>=0;i--)
    {
    if(!visit2[T[i]])
    {
    dfs2(T[i]);
    Bcnt
    ++;
    }
    }
    for(i=0;i<2*n;i++)
    {
    if(Belong[i]==Belong[i+2*n]) break;
    }
    if(i>=2*n)
    {
    ans
    =mid;left=mid+1;
    }
    else right=mid-1;
    }
    printf(
    "%d\n",ans);
    }
    return 0;
    }
    /*
    POJ 2723 Get Luffy Out
    AC代码
    */
    #include
    <stdio.h>
    #include
    <math.h>
    #include
    <iostream>
    using namespace std;
    const int MAXN=1<<12;
    const int MAXM=1<<24;
    int n,m;
    struct Node
    {
    int l,r;
    }e[MAXN];
    struct Node1
    {
    int from,to,next;
    }edge[MAXM];
    int ecnt;
    int head[MAXN],Belong[MAXN],Stack[MAXN];
    int top,idx,b_cnt;
    int hash[MAXN];
    int DFN[MAXN],LOW[MAXN];
    bool Instack[MAXN];
    void add(int a,int b)
    {
    edge[ecnt].from
    =a;edge[ecnt].to=b;edge[ecnt].next=head[a];head[a]=ecnt++;

    }
    void Tarjan(int u)
    {
    int i,v;
    DFN[u]
    =LOW[u]=(++idx);
    Stack[
    ++top]=u;
    Instack[u]
    =true;
    for(i=head[u];i!=-1;i=edge[i].next)
    {
    v
    =edge[i].to;
    if(!DFN[v])
    {
    Tarjan(v);
    if(LOW[u]>LOW[v])LOW[u]=LOW[v];
    }
    else if(Instack[v]&&LOW[u]>DFN[v])
    LOW[u]
    =DFN[v];
    }
    if(LOW[u]==DFN[u])
    {
    b_cnt
    ++;
    do
    {
    v
    =Stack[top--];
    Instack[v]
    =false;
    Belong[v]
    =b_cnt;
    }
    while(u!=v);
    }

    }
    int solve()
    {
    int i;
    b_cnt
    =idx=top=0;
    for(i=0;i<4*n;i++)
    {
    DFN[i]
    =LOW[i]=0;
    Belong[i]
    =0;
    Instack[i]
    =false;
    }
    for(i=0;i<4*n;i++)
    if(!DFN[i]) Tarjan(i);
    for(i=0;i<2*n;i++)
    {
    if(Belong[i]==Belong[i+2*n])
    return 0;
    }
    return 1;
    }
    int main()
    {
    int i,j;
    int right,left,mid,ans;
    while(scanf("%d%d",&n,&m)!=EOF)
    {

    if(n==0&&m==0)break;
    int a,b;
    for(i=0;i<n;i++)
    {
    scanf(
    "%d%d",&a,&b);
    hash[a]
    =b;
    hash[b]
    =a;
    }
    for(i=0;i<m;i++)
    scanf(
    "%d%d",&e[i].l,&e[i].r);
    left
    =0;
    right
    =m;
    while(left<=right)
    {
    mid
    =(left+right)/2;
    for(i=0;i<4*n;i++)
    {
    head[i]
    =-1;
    }
    ecnt
    =0;
    for(i=0;i<2*n;i++)
    {
    add(i,hash[i]
    +2*n);
    }
    for(i=0;i<mid;i++)
    {

    if(e[i].l!=e[i].r)
    {
    add(e[i].l
    +2*n,e[i].r);
    add(e[i].r
    +2*n,e[i].l);
    }
    if(e[i].l==e[i].r)
    {
    add(e[i].l
    +2*n,e[i].l);
    }

    }

    if(solve())
    {
    ans
    =mid;left=mid+1;
    }
    else right=mid-1;
    }
    printf(
    "%d\n",ans);
    }
    return 0;
    }
  • 相关阅读:
    C# Using MySQL
    C++ Asynchronous IO on Windows
    C++ Bind adapter usage
    C# Entity Framework with MSSQL, MYSQL
    Read a file into array for C++/C#
    上下移动 04.16
    盒子模型001基础
    JavaScript&JQ 001_五角星评分
    jQuery EasyUI tree的 使用
    自定义实现URL重写 04.18
  • 原文地址:https://www.cnblogs.com/kuangbin/p/2152038.html
Copyright © 2011-2022 走看看