hdu1816 + POJ 2723开锁(二分+2sat)
题意:
有m层门,我们在最外层,我们要一层一层的进,每一层上有两把锁,我们只要开启其中的一把们就会开,我们有n组钥匙,每组两把,我们只能用其中的一把,用完后第二把瞬间就会消失,问你最多能开到多少层们。
思路:
果断二分+2sat,现在我们来看下怎么建边,首先我们把每把钥匙用看成a,不用看成~a ,对于没一组钥匙,我们不能同时选择两个,所以有 x ->~y ,y -> ~x,对于门,我们每次至少选择开一个,所以有 ~x -> y ,~y -> x,就这样二分每次重新建图就行了,顺便说下POJ2723 ,跟这个题目几乎差不多,但是唯一的区别就是那个题目每组钥匙不会重复,这个有可能是同一把钥匙属于多个组,如果用这个题目的代码直接去交POJ2723,直接就可以AC了,钥匙反过来就不一定了,因为那个题目既然说是一把钥匙最多只出现在一组,那么就没有必要把每把钥匙拆成a
和 ~a ,而是把每组的钥匙拆成 a ~a,这样就节省了点数和时间,同时也没有必要建 x ->~y y->~x,这样也节省的边,如果是那么做的,那么到这个题目上就WA了,所以我说这个代码粘到那个代码上肯定AC,反过来就不一定了。
#include<stdio.h>
#include<string.h>
#include<stack> #define N_node 5000
#define N_edge 50000
using namespace std; typedef struct
{
int to ,next;
}STAR; STAR E1[N_edge] ,E2[N_edge];
int list1[N_node] ,list2[N_node] ,tot;
int Belong[N_node] ,cnt;
int mark[N_node];
int D[N_node][2] ,A[N_node][2];
int id[N_node];
stack<int>st; void add(int a ,int b)
{
E1[++tot].to = b;
E1[tot].next = list1[a];
list1[a] = tot;
a = a + b ,b = a - b ,a = a - b;
E2[tot].to = b;
E2[tot].next = list2[a];
list2[a] = tot;
} void DFS1(int s)
{
mark[s] = 1;
for(int k = list1[s] ;k ;k = E1[k].next)
if(!mark[E1[k].to]) DFS1(E1[k].to);
st.push(s);
} void DFS2(int s)
{
mark[s] = 1;
Belong[s] = cnt;
for(int k = list2[s] ;k ;k = E2[k].next)
if(!mark[E2[k].to]) DFS2(E2[k].to);
} bool ok(int mid ,int n)
{
memset(list1 ,0 ,sizeof(list1));
memset(list2 ,0 ,sizeof(list2));
tot = 1;
for(int i = 1 ; i<= n/2 ;i ++)
{
int x = A[i][0] * 2 ,xx = A[i][0] * 2 + 1;
int y = A[i][1] * 2 ,yy = A[i][1] * 2 + 1;
add(x ,yy) ,add(y ,xx);
} for(int i = 1 ;i <= mid ;i ++)
{
int x = D[i][0] * 2 ,xx = D[i][0] * 2 + 1;
int y = D[i][1] * 2 ,yy = D[i][1] * 2 + 1;
add(xx ,y) ,add(yy ,x);
}
memset(mark ,0 ,sizeof(mark));
while(!st.empty()) st.pop();
for(int i = 0 ;i < n * 2 ;i ++)
if(!mark[i]) DFS1(i);
memset(mark ,0 ,sizeof(mark));
cnt = 0;
while(!st.empty())
{
int xin = st.top();
st.pop();
if(mark[xin]) continue;
cnt ++;
DFS2(xin);
}
int mk = 0;
for(int i = 0 ;i < n * 2 && !mk;i += 2)
if(Belong[i] == Belong[i^1]) mk = 1;
return !mk;
} int main ()
{
int i ,n ,m ,a ,b;
while(~scanf("%d %d" ,&n ,&m) && n + m)
{
for(i = 1 ;i <= n ;i ++)
{
scanf("%d %d" ,&a ,&b);
A[i][0] = a ,A[i][1] = b;
}
for(i = 1 ;i <= m ;i ++)
scanf("%d %d" ,&D[i][0] ,&D[i][1]);
int low ,up , mid ,ans = 0;
low = 0 ,up = m ,n *= 2;
while(low <= up)
{
mid = (low + up) >> 1;
if(ok(mid ,n))
ans = mid ,low = mid + 1;
else up = mid - 1;
}
printf("%d\n" ,ans);
}
return 0;
}
hdu1816 + POJ 2723开锁(二分+2sat)的更多相关文章
- poj 2723 Get Luffy Out 2-SAT
两个钥匙a,b是一对,隐含矛盾a->!b.b->!a 一个门上的两个钥匙a,b,隐含矛盾!a->b,!b->a(看数据不大,我是直接枚举水的,要打开当前门,没选a的话就一定要选 ...
- 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="">题目链接 ...
- HDU 3622 Bomb Game(二分+2SAT)
题意:有一个游戏,有n个回合,每回合可以在指定的2个区域之一放炸弹,炸弹范围是一个圈,要求每回合的炸弹范围没有重合.得分是炸弹半径最小的值.求可以得到的最大分数. 思路:二分+2SAT. 二分炸弹范围 ...
- java模拟开锁
java模拟开锁 service qq:928900200 Introduction to Computer Science II: CSCI142Fall 2014Lab #1Instructor: ...
- 4位开锁<dfs>
题意: 有一个四位密码的锁,每一位是1~9的密码,1跟9相连.并且相邻的连个密码位可以交换.每改变一位耗时1s,给出锁的当前状态和密码,求最少解锁时间. 思路: 用bfs枚举出所有相邻交换的情况,并记 ...
- hihocoder 1075 : 开锁魔法III
描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜将会随机地选择 k 个盒子用魔法将它 ...
- #1075 : 开锁魔法III
描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜将会随机地选择 k 个盒子用魔法将它 ...
- Hiho #1075: 开锁魔法III
Problem Statement 描述 一日,崔克茜来到小马镇表演魔法. 其中有一个节目是开锁咒:舞台上有 n 个盒子,每个盒子中有一把钥匙,对于每个盒子而言有且仅有一把钥匙能打开它.初始时,崔克茜 ...
随机推荐
- 干货!!!测试如何确定是前端bug还是后端bug
目前的项目大多数都是前后端分离的,当我们发现bug后不知道指派给哪位开发,指派错了不仅影响解决bug 的效率,还容易被开发怼.最主要的是人家会认为你不专业,不专,不专呀.废话少说,上干货(踩过的坑)! ...
- HDOJ-2087(KMP算法)
剪花布条 HDOJ-2087 本题和hdoj-1686相似,唯一不同的是这里的子串一定要是单独的.所以在确定有多少个子串时不能用前面的方法.而是在循环时,只要找到一个子串,i就不是++,而是+=子串的 ...
- CCF(公共钥匙盒):思维+模拟
公共钥匙盒 201709-2 这题的思路一开始不是很清晰,一开始想用贪心去做.但是发现按照题目的思路不对.所以这里采用的是类似于多项式的加减的处理. #include<iostream> ...
- JS(ES6)、Vue.js、node.js
JS行为(ESMAScript, JSdom, bom)$.ajax() <- (xmlhttpRequest由这个封装来的) -> axios(vue版) = ajax技术jque ...
- 如何在 ASP.Net Core 中使用 Serilog
记录日志的一个作用就是方便对应用程序进行跟踪和排错调查,在实际应用上都是引入 日志框架,但如果你的 日志文件 包含非结构化的数据,那么查询起来将是一个噩梦,所以需要在记录日志的时候采用结构化方式. 将 ...
- 【Azure Developer】Python 获取Micrisoft Graph API资源的Access Token, 并调用Microsoft Graph API servicePrincipals接口获取应用ID
问题描述 在Azure开发中,我们时常面临获取Authorization问题,需要使用代码获取到Access Token后,在调用对应的API,如servicePrincipals接口. 如果是直接调 ...
- idea启动项目address localhost:1099 is already in use异常解决
IDEA中启动Tomcat报错,Error running Tomcat7.0.52: Address localhost:1099 is already in use 或者是 java.rmi.se ...
- C# 调用HTTP接口两种方式
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net ...
- python3 循环位移动
python3 中 >> 为算术右移位,高位补符号位: <<为左移位,低位补0: 1 # 假如将一个无符号的数据val,长度为N,需要循环移动n位.可以利用下面的公式: 2 ...
- Hi3559AV100 NNIE开发(6)RFCN中NNIE实现关键线程函数->SAMPLE_SVP_NNIE_Rfcn_ViToVo()进行数据流分析
前面随笔给出了NNIE开发的基本知识,下面几篇随笔将着重于Mobilefacenet NNIE开发,实现mobilefacenet.wk的chip版本,并在Hi3559AV100上实现mobilefa ...