典型的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. 11gR2集群件任务角色分离(Job Role Separation)简介

       从11gR2版本开始,Oracle推荐使用不同的操作系统用户安装GI和数据库软件,例如:使用grid用户安装GI,使用Oracle用户安装数据库软件.当然,用户还是可以使用Oracle用户安装G ...

  2. swift 泛型的类型约束

    总结: 1.类型约束只能添加到泛型参量上面 2.关联类型是泛型参量: 3.关联类型可以通过 协议.关联类型名称的形式引用: func allItemsMatch<C1: Container, C ...

  3. ChromiumWebBrowser禁止鼠标右键和拖动

    在屏蔽之前先查看namespace CefSharp.WinForms内的代码 public class ChromiumWebBrowser : Control, IWebBrowserIntern ...

  4. upload 上传 加token 在 :headers='headers' 注意 不要直接写$refs.upload.headers = {} 这样vue会警告 修改组件内部变量

    upload 上传 加token 在 :headers='headers' 注意 不要直接写$refs.upload.headers = {} 这样vue会警告 修改组件内部变量 <Upload ...

  5. No-3.Linux 终端命令格式

    Linux 终端命令格式 01. 终端命令格式 command [-options] [parameter] 说明: command:命令名,相应功能的英文单词或单词的缩写 [-options]:选项 ...

  6. C++知识点总结(纯C++!!)

    1.重载函数是否能够通过函数返回值的类型不同来区分? 不可以.因为在C++编程中,函数的返回值可以忽略(不使用其返回值),程序中调用此时函数名相同和参数相同的两个函数对编译器和程序员来说是没有办法区分 ...

  7. N皇后递归

    问题: n皇后问题:输入整数n, 要求n个国际象棋的皇后,摆在 n*n的棋盘上,互相不能攻击,输出全部方案. #include <iostream> using namespace std ...

  8. 如何用纯 CSS 绘制一颗闪闪发光的璀璨钻石

    效果预览 按下右侧的"点击预览"按钮在当前页面预览,点击链接全屏预览. 在线演示 https://codepen.io/zhang-ou/pen/qYqwQp 可交互视频教程 此视 ...

  9. c++_方格填数(最新方法)

      方格填数 如下的10个格子 +--+--+--+ | | | |+--+--+--+--+| | | | |+--+--+--+--+| | | |+--+--+--+ (如果显示有问题,也可以参 ...

  10. git 项目相关

    工具篇:Sourcetree 和 Git Bash Sourcetree Git一款非常好用的可视化工具,方便管理项目.下载地址 https://www.sourcetreeapp.com/ Git ...