WA了半天才发现居然是因为没看见这道题有多组数据,wzfl。。。

题目大意:有N对钥匙,对于每一对钥匙,如果使用了其中一把,另一把钥匙就会消失。接下来有M扇门,每扇门上有两把锁,分别对应两把钥匙(锁会重复出现,每把钥匙也可以重复使用),打开其中任意一把就可以打开这扇门,再打开第m扇门后才可以去尝试打开第m+1扇门。问最多能打开多少扇门。

思路:每个钥匙都有使用与不使用两种状态且必须是其中一种状态,于是想到2-SAT,对于配对的钥匙a,b,使用了一个之后另一个就不能使用 ,所以在图中连边(a,¬b)和(b,¬a)。

对于每个门上的两个钥匙c,d,如果门能打开,就一定有一个钥匙被使用,所以如果不用其中一个,就必须用另外一个,所以在图中连边(¬c,d)和(¬d,c)。

由于必须从第一扇们门开始向后连续尝试开门,接下来通过二分就能找到可以打开的最大门数,对于每个门数e,处理前e个门的钥匙,如果该2-SAT有解,就说明可以打开e扇门,否则不行。

代码如下:

//POJ.2723
//Author: Prgl
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0) typedef long long ll;
typedef vector<int>vec; #define INF 0x3f3f3f3f
const int maxv = 1 << 14;
const int maxd = 1 << 15; int V;
vec G[maxv], rG[maxv];
stack<int>s;
bool used[maxv];
int cmp[maxv]; inline void add_edge(int from, int to)
{
G[from].push_back(to);
rG[to].push_back(from);
} void dfs(int v)
{
used[v] = true;
for (int i = 0; i < G[v].size(); i++)
{
if (!used[G[v][i]])
dfs(G[v][i]);
}
s.push(v);
} void rdfs(int v, int k)
{
cmp[v] = k;
used[v] = true;
for (int i = 0; i < rG[v].size(); i++)
{
if (!used[rG[v][i]])
rdfs(rG[v][i], k);
}
} int scc()
{
memset(used, 0, sizeof(used));
for (int v = 0; v < V; v++)
{
if (!used[v])
dfs(v);
}
memset(used, 0, sizeof(used));
int k = 0;
while (!s.empty())
{
int v = s.top();
s.pop();
if (!used[v])
rdfs(v, k++); } return k;
} int N, M, K;
int a[maxv], b[maxv];
int A[maxd], B[maxd]; bool C(int d)
{
for (int v = 0; v < V; v++)
{
G[v].clear();
rG[v].clear();
}
for (int i = 0; i < N; i++)
{
add_edge(a[i], b[i] + K);
add_edge(b[i], a[i] + K);
}
for (int i = 0; i < d; i++)
{
add_edge(B[i] + K, A[i]);
add_edge(A[i] + K, B[i]);
}
memset(cmp, 0, sizeof(cmp));
scc();
for (int i = 0; i < K; i++)
{
if (cmp[i] == cmp[i + K])
return false;
} return true;
} void solve()
{
K = N * 2;
V = N * 4;
int lo = 0, hi = M + 1;
while (hi - lo > 1)
{
int mi = (lo + hi) / 2;
if (C(mi))
lo = mi;
else
hi = mi;
}
cout << lo << endl;
} int main()
{
IOS;
cin >> N >> M;
while (N != 0 || M != 0)
{
for (int i = 0; i < N; i++)
cin >> a[i] >> b[i];
for (int i = 0; i < M; i++)
cin >> A[i] >> B[i];
solve();
cin >> N >> M;
} return 0;
}

POJ2723 题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. 详解ElasticAPM实现微服务的链路追踪(NET)

    前言 Elastic APM实现链路追踪,首先要引用开源的APMAgent(APM代理),然后将监控的信息发送到APMServer,然后在转存入ElasticSearch,最后有Kibana展示:具体 ...

  2. 第05讲:Flink SQL & Table 编程和案例

    Flink系列文章 第01讲:Flink 的应用场景和架构模型 第02讲:Flink 入门程序 WordCount 和 SQL 实现 第03讲:Flink 的编程模型与其他框架比较 第04讲:Flin ...

  3. 安装Windows11操作系统(不需要绕过TPM检测脚本等) - 初学者系列 - 学习者系列文章

    Windows11操作系统是去年微软公司的最新力作.对于该操作系统的安装,网上有很多的教程了.这次主要写的是不需要绕过TPM检测操作安装Windows11操作系统. 1.        制作启动U盘: ...

  4. Java 后台线程介绍

    一  是啥? package com.aaa.threaddemo; /* * 一 Java后台线程? * 守护线程--也称"服务线程",他是后台线程, * 它有一个特性,即为用户 ...

  5. URL跳转空白页参数传递封装

    这东西主要是为了vue和平时打开一个空白界面_blank时的参数传递,不涉及到浏览器存储(session,local等) 众所周知,请求传参无非就用的query和params,相对应就是get和pos ...

  6. C程序:年转化天

    突然想算算自己到底活了多少天了,e,就是纯属为了好玩,毕竟咱作为一名C初学者还是要多练练的- 为了好玩,加了个密码登陆的,密码是521,还有就是不太懂时间获取... 具体闰年的判断方法: 代码如下: ...

  7. 通过版本号来判断用户是否是第一次登陆----By张秀清

    @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)appl ...

  8. 键盘弹起及lab时的动态计算高度 --董鑫

    1.键盘抬起或掉下时,动态计算高度 2.动态计算Label的高度 计算的高度时,numberOfLines必须设置为0: 2.1  ios7.0之后 2.2 iOS 7.0之前

  9. Keepalived配置与使用(1)

    介绍 Keepalived是一个基于VRRP协议来实现的WEB服务高可用方案,可以利用其来避免单点故障.一个WEB服务至少会有2台服务器运行Keepalived,一台为主服务器(MASTER),一台为 ...

  10. MHA高可用配置及故障切换

    MHA高可用配置及故障切换 目录 MHA高可用配置及故障切换 一.案例概述 二.案例前置知识点 1. MHA概述 2. MHA的组成 (1)MHA Manager(管理节点) (2)MHA Node( ...