zoukankan      html  css  js  c++  java
  • poj 2723 Get Luffy Out (2 sat + 二分)

    http://poj.org/problem?id=2723

    题意:

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

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

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

    题解:

    通过这道题 ,对 2-sat  有了 进一步的了解。。。。。

    2-SAT主要是寻找不相容的点(建图),首先是

    我们把钥匙分为 选和不选,A和 !A

    对于 第一类 : 没两把钥匙 ,a和b  ( 必然关系 ) 选 a 不选 b(a->!b) ,选 b 不选 a(b->!a);

     对于 第二类:

    每一扇门  有 a 锁和 b 锁,不开a 必开 b (!a->b),,不开b 必开 a(!b->a),///一开始 建图减成了 a-> !b  和 b-> !a (这样是 不对的

    因为每扇门至少要开一把锁,我们要找的是 必须的 关系
    )

    因为 门 是 顺序的 ,所以要  二分枚举。

      1 #include<cstdio>
      2  #include<cstring>
      3  #include<cmath>
      4  #include<iostream>
      5  #include<algorithm>
      6  #include<set>
      7  #include<map>
      8  #include<queue>
      9  #include<vector>
     10  #include<string>
     11  #define Min(a,b) a<b?a:b
     12  #define Max(a,b) a>b?a:b
     13  #define CL(a,num) memset(a,num,sizeof(a));
     14  #define eps  1e-12
     15  #define inf 100000000
     16  #define mx 1<<60
     17  #define ll   __int64
     18  const double pi  = acos(-1.0);
     19  const int maxn = 5000;
     20  using namespace std;
     21  int  top,num,bcnt,belong[maxn],instack[maxn],stack[maxn],dfn[maxn],low[maxn];
     22  int n ,m;
     23  int a[maxn],b[maxn],c[maxn],d[maxn];
     24  struct pnode
     25  {
     26      int to;
     27      int next;
     28  }p[maxn*2];
     29 
     30  int cnt ,next[maxn];
     31  void add(int u,int v)
     32  {
     33      p[cnt].to = v;
     34      p[cnt].next  = next[u];
     35      next[u] = cnt++;
     36 
     37  }
     38  void tarjan(int i)
     39  {
     40      int j,k;
     41      dfn[i] = low[i] = ++num;
     42      stack[++top] = i;
     43      instack[i] = 1;
     44      for(k = next[i] ; k != -1;k = p[k].next)
     45      {
     46 
     47           j = p[k].to ;
     48          if(!dfn[j])
     49          {
     50              tarjan(j);
     51              if(low[j] < low[i]) low[i] = low[j] ;
     52          }
     53          else
     54          {
     55              if(instack[j] && dfn[j] < low[i]) low[i] = dfn[j] ;
     56          }
     57 
     58      }
     59      if(dfn[i] == low[i])
     60      {
     61          bcnt++;
     62          do
     63          {
     64              j = stack[top--];
     65              instack[j] = 0 ;
     66              belong[j] = bcnt ;
     67          }while(j != i);
     68      }
     69  }
     70  void solve()
     71  {
     72      int i, l;
     73      for(i =0 ; i <= n*4;i++)
     74      {
     75          dfn[i] = low[i] = instack[i] = stack[i] = belong[i] = 0;
     76      }
     77      top = bcnt = num = 0;
     78      for(i = 0 ; i < n*4;i++)
     79      {
     80          if(!dfn[i])tarjan(i);
     81      }
     82 
     83 
     84 
     85  }
     86  void init()
     87  {
     88      CL(next,-1);
     89      cnt = 0 ;
     90 
     91  }
     92  bool judge()
     93  {
     94      for(int i = 0 ; i < 2*n;i++)
     95      {
     96          if(belong[i] == belong[i + 2*n])
     97           return false ;
     98      }
     99      return true ;
    100  }
    101  int main()
    102  {
    103      int i,j;
    104 
    105      //freopen("data.txt","r",stdin) ;
    106 
    107     while(scanf("%d%d",&n,&m),n+m)
    108     {
    109 
    110         for(i = 1 ;i <= n;i++)
    111         {
    112             scanf("%d%d",&a[i],&b[i]);
    113 
    114         }
    115         for(i = 1;i <= m;i++)
    116         {
    117             scanf("%d%d",&c[i],&d[i]);
    118 
    119         }
    120         int l = 0,r = m ;
    121         int ans = 0 ;
    122         while(l <= r)
    123         {
    124             init();
    125             int mid = (l+r)>>1;
    126             for(i = 1; i<= n;i++)
    127             {
    128                 add(a[i],b[i] + n*2);
    129                 add(b[i],a[i] + n*2);
    130             }
    131             for(i = 1;i <= mid;i++)
    132             {
    133                 add(c[i] + n*2,d[i] );
    134                 add(d[i] + n*2,c[i] );
    135             }
    136             solve() ;
    137             if(judge())
    138             {
    139 
    140                  l = mid + 1;
    141                  ans = mid ;
    142             }
    143             else  r = mid - 1;
    144         }
    145         printf("%d\n",ans);
    146     }
    147  }

  • 相关阅读:
    极大/小搜索,alpha/beta剪枝
    消息系统
    渲染主线程都在干什么
    好玩的虚拟CPU执行代码
    好玩的隐藏属性
    好玩的对象存储
    透视投影矩阵
    绕任意轴旋转
    视图变换
    正交投影矩阵
  • 原文地址:https://www.cnblogs.com/acSzz/p/2672611.html
Copyright © 2011-2022 走看看