典型的2-sat问题,题意:有m个门,每个门上俩把锁,开启其中一把即可,现在给n对钥匙(所有

钥匙编号0123456...2n-1),每对钥匙只能用一把,要求尽可能开门多(按顺序,前max个)。

关键是题意的分析与转化,只能选一?必然2-sat,每给一对门上的锁对应钥匙的编号,说:必需要这

俩把钥匙的一把(至少),即:a^b,所以,建图了可以,总结通法:对应的数据编号:0123..,每个

数代表原来的一个“状态”/“命题”/“数据”,使之01为一对(只取一个),23一对,...依次,建图

此题要求最值,二分即可。

注意点(WA之因):1.编号后全图全按编号走啊!原来数据基本无用,只是有时候输出时之用,或建立

数据双向关系!2.对于每次二分,对应数要重新建图,注意初始化!

ps:一晚没成功,结果早上起来2分钟,AC!上午效率就是高!切记不可熬夜!身体健康第一位!

#include<iostream>    //36MS
#include<cstring>
#include<cstdio>
#include<stack>
#include<vector>
using namespace std;
const int MAX=3000;
vector<int>keys(MAX);int n,m;int times=0;
int belong[MAX];
int low[MAX];int dfn[MAX];int visited[MAX];int isinstack[MAX];stack<int>s;
int scc[MAX];int numblock=0;
struct request //条件
{
int a,b;
};
request requests[MAX];
vector<vector<int> >edges(MAX); //图
void clear()
{
times=numblock=0;
for(int i=0;i<2*n;i++)
{
visited[i]=dfn[i]=low[i]=isinstack[i];
scc[i]=-1;
edges[i].clear();
}
}
void tarjan(int u) //dfs
{
dfn[u]=low[u]=++times;
isinstack[u]=1;
s.push(u); int len=edges[u].size();
for(int i=0;i<len;i++)
{
int v=edges[u][i];
if(visited[v]==0)
{
visited[v]=1;
tarjan(v);
if(low[u]>low[v])low[u]=low[v];
}
else if(isinstack[v]&&dfn[v]<low[u])
low[u]=dfn[v];
}
if(low[u]==dfn[u])
{
numblock++;int cur;
do
{
cur=s.top();s.pop();
isinstack[cur]=0;
scc[cur]=numblock;
}while(cur!=u);
}
}
bool check(int maxnum) //检查
{
clear();
for(int i=0;i<maxnum;i++) //这里的数据的转化
{
if(requests[i].a==requests[i].b)
{
edges[belong[requests[i].a]^1].push_back(belong[requests[i].b]);
}
else
{
edges[belong[requests[i].a]^1].push_back(belong[requests[i].b]);
edges[belong[requests[i].b]^1].push_back(belong[requests[i].a]);
}
}
for(int i=0;i<2*n;i++)
if(visited[i]==0)
{
visited[i]=1;
tarjan(i);
}
for(int i=0;i<2*n;i+=2)
if(scc[i]==scc[i+1]) //因为这里跪了半天!注意编号!图顶点用的都是编号!
return 0;
return 1;
}
void readin()
{
for(int i=0;i<2*n;i++)
{
scanf("%d",&keys[i]);
belong[keys[i]]=i;
}
for(int i=0;i<m;i++)
{
scanf("%d%d",&requests[i].a,&requests[i].b);
}
}
int main()
{
while(~scanf("%d%d",&n,&m)&&(n||m))
{
readin();
int left=0,right=m,mid;
int count=-1;
while(right>left) //二分之
{
mid=(left+right)/2;
if(mid==count&&mid==left) //注意出口!
{
if(check(left+1))left++;
break;
}
if(check(mid))
left=mid;
else right=mid;
count=mid;
}
printf("%d\n",left);
}
}

poj2723 2sat判断解+二分的更多相关文章

  1. BZOJ 2199: [Usaco2011 Jan]奶牛议会 [2-SAT 判断解]

    http://www.lydsy.com/JudgeOnline/problem.php?id=2199 题意:裸的2-SAT,但是问每个变量在所有解中是只能为真还是只能为假还是既可以为真又可以为假 ...

  2. hdu3715 Go Deeper[二分+2-SAT]/poj2723 Get Luffy Out[二分+2-SAT]

    这题转化一下题意就是给一堆形如$a_i + a_j \ne c\quad (a_i\in [0,1],c\in [0,2])$的限制,问从开头开始最多到哪条限制全是有解的. 那么,首先有可二分性,所以 ...

  3. hdu 3622(二分+2-sat判断可行性)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3622 思路:二分是容易想到的,由于题目中有明显的矛盾关系,因此可以用2-sat来验证其可行性.关键是如 ...

  4. 【判断解是否可行-二分】POJ1064-Cable master

    http://poj.org/problem?id=1064 [题目大意] 给出几条绳子的长度,问如果要切出k条长度相等的绳子,这k条绳子最常多长? [思路] 二分.把下界设为0,上界设为所有绳子长度 ...

  5. hdu3622 2-sat问题,二分+判断有无解即可。

    /*2-sat问题初破!题意:每一对炸弹只能选一个(明显2-sat),每个炸弹半径自定,爆炸范围不可 相交,求那个最小半径的最大值(每种策略的最小半径不同).思:最优解:必然是选择的点最近 的俩个距离 ...

  6. POJ 3683 Priest John's Busiest Day[2-SAT 构造解]

    题意: $n$对$couple$举行仪式,有两个时间段可以选择,问是否可以不冲突举行完,并求方案 两个时间段选择对应一真一假,对于有时间段冲突冲突的两人按照$2-SAT$的规则连边(把不冲突的时间段连 ...

  7. Uva LA 3177 - Beijing Guards 贪心,特例分析,判断器+二分,记录区间内状态数目来染色 难度: 3

    题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

  8. The Accomodation of Students HDU - 2444(判断二分图 + 二分匹配)

    The Accomodation of Students Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ( ...

  9. hdu 2444 The Accomodation of Students 判断二分图+二分匹配

    The Accomodation of Students Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ( ...

随机推荐

  1. python之路——内置函数和匿名函数

    阅读目录 楔子 内置函数 匿名函数 本章小结 楔子 在讲新知识之前,我们先来复习复习函数的基础知识. 问:函数怎么调用? 函数名() 如果你们这么说...那你们就对了!好了记住这个事儿别给忘记了,咱们 ...

  2. largest rectangle in histogram leetcode

    Given n non-negative integers representing the histogram's bar height where the width of each bar is ...

  3. CWnd::Updata的作用

    CWnd::Updata的作用 CWnd::UpdateData 调用此成员函数以在对话框中初始化数据,或者取回和验证对话框数据. BOOL UpdateData(BOOL bSaveAndValid ...

  4. SQL使用exists时的多种写法

    from test; go from test; go 下面这种效率明显高不少.

  5. CPP-STL:vector容器

    1.     vector容器简介: vector向量容器是一种随机访问的数组类型,它提供了对数组元素的快速访问.随机访问,以及在序列尾部快速.随机地插入和删除操作.它类似于数据结构中的队列.数组和堆 ...

  6. HTTP初步了解

    HTTP协议简介 HTTP(超文本传输协议)是应用层上的一种客户端/服务端模型的通信协议,它由请求和响应构成,且是无状态的.(暂不介绍HTTP2) 协议 协议规定了通信双方必须遵循的数据传输格式,这样 ...

  7. Dubbo框架的说明

    说实话,自己现在做的项目中有用到dubbo,但是我所负责的那一个模块,并没有涉及到dubbo,想学习一下dubbo,之前是没有学习完,这次继续... 一.背景知识总结 二.服务治理 三.Dubbo架构 ...

  8. ubuntu下操作Hadoop、hdfs、hbase、zookeeper时产生的一些问题及解决办法

    2019/05/29 1.在终端输入jps时,没有显示Hdfs的DataNode 在文件夹中分别找到DataNode 和Namenode的version,将Datanode的version改为与nam ...

  9. 全新Ubentu系统没有make,gcc命令解决办法

    一定要记得先update sudo apt-get update 然后输入下述命令即可 sudo apt-get install make sudo apt-get install gcc

  10. minGW64编译Qt

    1.安装minGW64,设置bin目录到环境变量Path 2.cmd 到qt的Src目录 3.configure -debug-and-release -opensource -prefix &quo ...