题目链接: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 OutAC代码 */

#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 OutAC代码 */#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;}   

ACM POJ 2723 Get Luffy Out(2-SAT入门)相关推荐

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

    HDU 1816, POJ 2723 Get Luffy Out 题目链接 题意:N串钥匙.每串2把,仅仅能选一把.然后有n个大门,每一个门有两个锁,开了一个就能通过,问选一些钥匙,最多能通过多少个门 ...

  2. POJ 2723 Get Luffy Out【二分+2-sat】

    题意:已知有 2*n把钥匙,这些钥匙两两一组,每组只能用其中的一把钥匙,有 m 个门,每个门上有两把锁,只要有一把锁被打开门就可以被打开, 一个门上可能是两把相同的锁,不同的门上也有可能有相同的锁,给 ...

  3. ACM POJ 题目分类(完整整理版本)

    DP: 1011   NTA                 简单题  1013   Great Equipment     简单题  1024   Calendar Game       简单题   ...

  4. ACM POJ 2965 The Pilots Brothers' refrigerator

    http://poj.org/problem?id=2965 The Pilots Brothers' refrigerator Time Limit: 1000MS Memory Limit: 65 ...

  5. [ACM] POJ 1664 放苹果(n个相同小球放入m个相同盒子)

    放苹果 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 25952   Accepted: 16509 Description ...

  6. 可行性nullpoj 2723 Get Luffy Out 2sat

    最近研究可行性null,稍微总结一下,以后继续补充: 二分+2sat判可行性 每日一道理 最为值得珍惜的是今天,因为最容易流逝的就是今天,把握今天就是把握希望,分分秒秒只是瞬间,而所乘载的分分秒秒就叫 ...

  7. hdu1816 + POJ 2723开锁(二分+2sat)

    题意:      有m层门,我们在最外层,我们要一层一层的进,每一层上有两把锁,我们只要开启其中的一把们就会开,我们有n组钥匙,每组两把,我们只能用其中的一把,用完后第二把瞬间就会消失,问你最多能开到 ...

  8. ACM POJ 2192 Zipper

    题目大意:输入字符串a,b,c 要求推断c是否有a,b中的个字符保持原有顺序组合而成. 算法思想: DP 用dp[i][j]表示a的前0~i-1共i个字符和b的前0~j-1共j个字符是否构成c[i+j ...

  9. poj 2723 2-SAT问题

    思路:二分枚举能开的门的数量,将每次枚举转换成2-SAT问题.这里存在的矛盾是假设有门上a,b两个锁,a锁对应于1号钥匙,而一号钥匙的配对是2号钥匙,b锁对应于3号钥匙,3号的配对是4号钥匙.那么2号 ...

最新文章

  1. FactoryMethod工厂方法模式升级成AbstractFactory抽象工厂模式
  2. 作者:秦兵(1968-),女,哈尔滨工业大学计算机科学与技术学院教授、博士生导师。...
  3. HID API for Linux, Mac OS X, and Windows
  4. wordpress文章发布时区时间延迟8小时解决方法
  5. 【语音隐写】基于matlab DWT音频数字水印嵌入提取【含Matlab源码 350期】
  6. 爆强的一句话,工作之余放松放松!
  7. 自动登录北科大USTB校园网
  8. oracle+sql+groupby,oracle学习笔记2:SQL执行
  9. python编程入门读书笔记1
  10. 以集成和管理为主要手段的企业报表中心架构设计
  11. 函数相乘和相除的导数及证明
  12. C++中的sort函数排序(快速排序)
  13. 如何查看本地服务器名称
  14. 按照拼音排序的SQL语句条件
  15. 2021-2027全球与中国成像色度计市场现状及未来发展趋势
  16. 常用IP地址端口对照表
  17. 【量化交易】量化分析概览
  18. 华硕主板如何用u盘启动计算机,华硕主板u盘启动是按f几_华硕主板BIOS设置U盘启动的方法-win7之家...
  19. 【网络攻击与防御】关于防御DDoS攻击的防火墙技术概述
  20. ALOS PALSAR卫星轨道参数读取

热门文章

  1. 【洛谷p1058】立体图(已完结)
  2. ruby简单的基础 4
  3. nodejs实现的简单接口
  4. 银行加速“去房地产化”
  5. 计算器是如何计算sin、cos等科学函数的值呢?
  6. C++--深入分析MFC文档视图结构(项目实践)
  7. CSS综合征病例,医药-churg-strauss 综合征 (css) 变应性嗜酸性肉芽肿.ppt
  8. java servlet 请求_java servlet请求数据
  9. 1.3 程序示例--梯度下降-机器学习笔记-斯坦福吴恩达教授
  10. MT6573驱动开发日志之touchpanel .