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\n",ans);
88 }
89 return 0;
90 }

LOJ2723的更多相关文章

随机推荐

  1. java的注释方法

    1.单行注释 //注释的内容 2.多行注释 /....../ 3./**......*/,这种方式和第二种方式相似.这种格式是为了便于javadoc程序自动生成文档.

  2. Spring IOC 笔记

    什么是IOC与DI IOC(inversion of control) 它描述的其实是一种面向对象编程中的设计原则,用来降低代码之间的耦合度, 而DI(dependency Injection)依赖注 ...

  3. std::thread线程详解(1)

    目录 目录 简介 线程的使用 线程的创建 线程的方法和属性 std::jthread (C++20) stop_token (C++20) 总结 Ref 简介 本文主要介绍了标准库中的线程部分.线程是 ...

  4. LVS、Nginx和HAProxy区别

    LVS.Nginx和HAProxy区别 LVS 优点: 高并发连接:LVS基于内核网络层面工作,有超强的承载能力和并发处理能力.单台LVS负载均衡器,可支持上万并发连接. 抗负载能力强:是工作在网络4 ...

  5. dalao高精

    #ifndef MY_BIGN_H#define MY_BIGN_H 1#pragma GCC system_header#include<cstring>#include<algo ...

  6. TurtleBot3使用课程-第三节b(北京智能佳)

    目录 1.使用TurtleBot3机械手运行SLAM 2 1.1 roscore运行 2 1.2 准备行动 3 1.3 运行SLAM节点 3 1.4 运行turtlebot3_teleop_key节点 ...

  7. 每日一个linux命令5 -- rm

    rm命令.rm是常用的命令,该命令的功能为删除一个目录中的一个或多个文件或目录,它也可以将某个目录及其下的所有文件及子目录均删除.对于链接文件,只是删除了链接,原有文件均保持不变. rm是一个危险的命 ...

  8. 【剑指 Offer】04.二维数组中的查找

    题目描述 在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. ...

  9. oracle坚决不挂01(表,索引,视图的创建,修改,删除,查询)

    考试快来了,来篇oracle干货,复习一下(挣扎一下) 废话不多说,开始写! 这篇是数据库对象的有关操作的总结! 数据库对象有熟悉的表,视图,索引,序列,同义词等(这个oracle东西真不少,小声bb ...

  10. MongoDB备份(mongodump)与恢复(mongorestore)工具实践

    mongodump和mongorestore实践 1.mongodump备份工具 mongodump能够在Mongodb运行时进行备份,它的工作原理是对运行的Mongodb做查询,然后将所有查到的文档 ...