zoukankan      html  css  js  c++  java
  • LOJ2723

    LOJ2723 Get Luffy Out

    题目大意:给你n对钥匙,每对钥匙只可以用其中的任意一个,钥匙有编号,且不重复。有m个大门,每个门上有两个锁,每个锁对应一个编号的钥匙,只要打开两个锁中的一个就可以打开门。问用这n对钥匙最多可以打开多少大门(门有顺序)?

    ——————————————————————————————————————————————

    每一个大门要打开,要么用A钥匙,要么用B钥匙,这是明现的2-SAT问题。

    同一对钥匙,用了A钥匙就一定不能用B钥匙。

    对于最多可以打开多少门,因为门有顺序,所以要二分答案。

    ——————————————————————————————————————————————

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 const int maxn=1050;
     7 const int maxm=2100;
     8 int n,m;
     9 int keys[maxn<<1],doors[maxm][2];
    10 struct edge
    11 {
    12     int u,v,nxt;
    13 }e[maxm<<1];
    14 int head[maxn<<1],js;
    15 void addage(int u,int v)
    16 {
    17     e[++js].u=u;e[js].v=v;
    18     e[js].nxt=head[u];head[u]=js;
    19 }
    20 int low[maxm<<1],dfn[maxm<<1],cnt,st[maxm<<1],top,lt[maxm<<1],lts;
    21 void tarjan(int u)
    22 {
    23     low[u]=dfn[u]=++cnt;
    24     st[++top]=u;
    25     for(int i=head[u];i;i=e[i].nxt)
    26     {
    27         int v=e[i].v;
    28         if(!dfn[v])
    29         {
    30             tarjan(v);
    31             low[u]=min(low[u],low[v]);
    32         }
    33         else if(!lt[v]) low[u]=min(low[u],dfn[v]);
    34     }
    35     if(low[u]==dfn[u])
    36     {
    37         lt[u]=++lts;
    38         while(st[top]!=u)lt[st[top--]]=lts;
    39         --top;
    40     }
    41 }
    42 bool pd(int x)
    43 {
    44     memset(head,0,sizeof head);
    45     js=0;
    46     for(int a,b,i=0;i<x;++i)
    47     {
    48         a=doors[i][0],b=doors[i][1];
    49         if(a==b)addage(keys[a]^1,keys[a]);
    50         else
    51         {
    52             addage(keys[a]^1,keys[b]);
    53             addage(keys[b]^1,keys[a]);
    54         }
    55     }
    56     memset(low,0,sizeof low);
    57     memset(dfn,0,sizeof dfn);
    58     cnt=0;
    59     memset(lt,0,sizeof lt);
    60     lts=0;
    61     top=0;
    62     for(int i=2;i<n*2+2;++i)
    63         if(!dfn[i])tarjan(i);
    64     for(int i=1;i<n+1;++i)
    65         if(lt[i<<1]==lt[(i<<1)^1])return 0;
    66     return 1;
    67 }
    68 int main()
    69 {
    70     while(scanf("%d%d",&n,&m),n+m)
    71     {
    72         for(int a,b,i=1;i<=n;++i)
    73         {
    74             scanf("%d%d",&a,&b);
    75             keys[a]=i<<1;
    76             keys[b]=(i<<1)^1;
    77         }
    78         for(int i=0;i<m;++i)
    79             scanf("%d%d",&doors[i][0],&doors[i][1]);
    80         int l=0,r=m,ans=0;
    81         while(l<=r)
    82         {
    83             int mid=(l+r)>>1;
    84             if(pd(mid))ans=mid,l=mid+1;
    85             else r=mid-1;
    86         }
    87         printf("%d
    ",ans);
    88     }
    89     return 0;
    90 }
    View Code
  • 相关阅读:
    关于前端基础框架的思考和尝试
    通过当前IP获取当前网卡的MAC地址
    shell及脚本2——shell 环境及命令
    shell及脚本1——变量
    linux显示git commit id,同时解决insmod模块时版本不一致导致无法加载问题
    大于16MB的QSPI存放程序引起的ZYNQ重启风险
    insmod模块的几种常见错误
    shell及脚本3——正则表达式
    修改/etc/profile和/etc/environment导致图形界面无法登陆的问题
    Sql 2008的merge关键字
  • 原文地址:https://www.cnblogs.com/gryzy/p/10929380.html
Copyright © 2011-2022 走看看