TTTTTTTTTTTTTTTT POJ 2723 楼层里救朋友 2-SAT+二分
| Time Limit: 2000MS | Memory Limit: 65536K | |
| Total Submissions: 8211 | Accepted: 3162 |
Description
Behind the large door, there is a nesting prison, which consists of M floors. Each floor except the deepest one has a door leading to the next floor, and there are two locks in each of these doors. Ratish can pass through a door if he opens either of the two locks in it. There are 2N different types of locks in all. The same type of locks may appear in different doors, and a door may have two locks of the same type. There is only one key that can unlock one type of lock, so there are 2N keys for all the 2N types of locks. These 2N keys were divided into N pairs, and once one key in a pair is used, the other key will disappear and never show up again.
Later, Ratish found N pairs of keys under the rock and a piece of paper recording exactly what kinds of locks are in the M doors. But Ratish doesn't know which floor Luffy is held, so he has to open as many doors as possible. Can you help him to choose N keys to open the maximum number of doors?
Input
Output
Sample Input
3 6
0 3
1 2
4 5
0 1
0 2
4 1
4 2
3 5
2 2
0 0
Sample Output
4 题意:有m层楼,从一层到m层,要进入每层都要打开位于该层的两道门中的至少一道。门锁有2n种,每个门锁为2n种中的一种,可以重复。有2n把钥匙,分别对应2n种锁,但是钥匙两两一组,共n组,每组只能选一个来开门,被选中的可以多次使用,另一个一次都不能用。问最多能上多少层。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long Ull;
#define MM(a,b) memset(a,b,sizeof(a));
const double eps = 1e-10;
const int inf =0x7f7f7f7f;
const double pi=acos(-1);
const int maxn=100+1000; int n,m,pre[2*maxn],lowlink[2*maxn],dfs_clock,sccno[2*maxn],scc_cnt;
int door[2*maxn][3],key[2*maxn]; vector<int> G[2*maxn];
stack<int> S; void readkey()
{
int u,v;
scanf("%d %d",&u,&v);
key[u]=v;
key[v]=u;
} void readdoor(int i)
{
int u,v;
scanf("%d %d",&u,&v);
door[i][0]=u;
door[i][1]=v;
} void tarjan(int u)
{
pre[u]=lowlink[u]=++dfs_clock;
S.push(u);
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i];
if(pre[v]==-1)
{
tarjan(v);
lowlink[u]=min(lowlink[u],lowlink[v]);
}
else if(!sccno[v])
lowlink[u]=min(lowlink[u],pre[v]);
} if(lowlink[u]==pre[u])
{
scc_cnt++;
while(1)
{
int x=S.top();S.pop();
sccno[x]=scc_cnt;
if(x==u) break;//找到了当前强连通的起始节点就退出,<br>//不然会破坏其他强连通分量
}
}
} void find_scc()
{
MM(pre,-1);
MM(sccno,0);
MM(lowlink,0);
scc_cnt=dfs_clock=0;
for(int i=0;i<2*n;i++)
if(pre[i]==-1)
tarjan(i);
} bool ok(int mid)
{
for(int i=0;i<2*n;i++)
{G[i].clear();} for(int i=1;i<=mid;i++)
{
int a=door[i][0],b=door[i][1];
G[key[a]].push_back(b);
G[key[b]].push_back(a);
}//建图,预先记录门与钥匙 find_scc();
for(int i=0;i<2*n;i++)
if(sccno[i]==sccno[key[i]])
return false;
return true;
} int main()
{
while(~scanf("%d %d",&n,&m)&&(n||m))
{
MM(key,0);MM(door,0);
for(int i=1;i<=n;i++)
readkey();
for(int i=1;i<=m;i++)
readdoor(i); int l=0,r=m+1;
while(r-l>1)
{
int mid=(l+r)>>1;
if(ok(mid)) l=mid;
else r=mid;
}
printf("%d\n",l);
}
return 0;
}
分析:经典题型,建图不再是以前的那种一个点对应两个(0,1)状态,而是一组数对应两个状态(只能取其中两个中的一个)
建图核心思路:对于确切的层数,对于一组数,设其中一个为x,则对应的另一个为f[x],如果一个门对应的数值为x,y两个,那么可以确定的是如果选f[x]的话,为了打开这门,必须选y,同理选f[y]的话,必须选x;
建图即可;再二分查找即可,tarjan求强连通复杂度(n+m)
易错点:
1,数组要开两倍,因为输入的n是组数;
TTTTTTTTTTTTTTTT POJ 2723 楼层里救朋友 2-SAT+二分的更多相关文章
- POJ 2723 Get Luffy Out(2-SAT+二分答案)
Get Luffy Out Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8851 Accepted: 3441 Des ...
- HDU 1816, POJ 2723 Get Luffy Out(2-sat)
HDU 1816, POJ 2723 Get Luffy Out pid=1816" target="_blank" style="">题目链接 ...
- poj 2456 Aggressive cows && nyoj 疯牛 最大化最小值 二分
poj 2456 Aggressive cows && nyoj 疯牛 最大化最小值 二分 题目链接: nyoj : http://acm.nyist.net/JudgeOnline/ ...
- poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分, dinic, isap
poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分 dinic /* * Author: yew1eb * Created Time: 2014年10月31日 星期五 ...
- poj 2723 Get Luffy Out 二分+2-sat
题目链接 给n个钥匙对, 每个钥匙对里有两个钥匙, 并且只能选择一个. 有m扇门, 每个门上有两个锁, 只要打开其中一个就可以通往下一扇门. 问你最多可以打开多少个门. 对于每个钥匙对, 如果选择了其 ...
- poj 2723
Get Luffy Out Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 7295 Accepted: 2778 Des ...
- poj 2723 2-SAT问题
思路:二分枚举能开的门的数量,将每次枚举转换成2-SAT问题.这里存在的矛盾是假设有门上a,b两个锁,a锁对应于1号钥匙,而一号钥匙的配对是2号钥匙,b锁对应于3号钥匙,3号的配对是4号钥匙.那么2号 ...
- poj 2723 Get Luffy Out(2-sat)
Description Ratish is a young man who always dreams of being a hero. One day his friend Luffy was ca ...
- POJ 2723 HDU 1816 Get Luffy Out
二分答案 + 2-SAT验证 #include<cstdio> #include<cstring> #include<cmath> #include<stac ...
随机推荐
- 面向对象编程 OOP
OOP,Object Oriented Programming,原来就是面向对象的编程. 面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物. OOD,Object Or ...
- oracle查询表的结构
SELECT t.table_name,t.column_name,t.data_type||'('||t.data_length||')', t1.comments FROM User_Tab_Co ...
- Luogu P2617 Dynamic Rankings(整体二分)
题目 动态区间第K小模板题. 一个非常可行的办法是BIT套动态开点权值SegTree,但是它跑的实在太慢了. 然后由于这题并没有强制在线,所以我们可以使用整体二分来吊打树套树. 当然如果强制在线的话就 ...
- WINDOWS7 系统中建立文件夹映射
如何在WIN7中建立文件夹映射,还有以及MKLINK的具体使用方法: 步骤如下: 1.以映射d盘1文件夹为例: 2.按win+r,输入cmd,点击确定: 3.提示符后输入mklink /J " ...
- copy小练习
# 1. # 有如下 # v1 = {'郭宝元', '李杰', '太白', '梦鸽'} # v2 = {'李杰', '景女神} # 请得到 v1 和 v2 的交集并输出 # 请得到 v1 和 v2 的 ...
- deepin 15.10.1 GTX1060 NVIDIA 驱动安装,双屏显示问题记录
有一段时间没有用Linux了.由于买了个4k的戴尔显示屏,在deepin系统上无法用,从昨晚到现在,总于解决了我的问题! 问题1:无法直接在深度的显卡驱动管理器哪里直接切换,网上看到很多人都有这个问题 ...
- @Resource与@Autowired注解的区别踩坑者入
一.写本博文的原因 有些童鞋搞不为什么要用@Resource或者@Autowired,咱们一起研究下 @Resource默认按照名称方式进行bean匹配,@Autowired默认按照类型方式进行bea ...
- 强大的开源企业级数据库监控利器Lepus
Lepus监控简单介绍 官方网站:http://www.lepus.cc 开源企业级数据库监控系统 简洁.直观.强大的开源数据库监控系统,MySQL/Oracle/MongoDB/Redis一站式性能 ...
- openlayers之全屏控件的使用
import { FullScreen } from 'ol/control' map.addControl(new FullScreen())
- Spring Boot【快速入门】简单案例
Spring Boot[快速入门] Spring Boot 概述 Build Anything with Spring Boot:Spring Boot is the starting point ...