POJ 2749 2SAT判定+二分
题意:图上n个点,使每个点都与俩个中转点的其中一个相连(二选一,典型2-sat),并使任意两点最大
距离最小(最大最小,2分答案),有些点相互hata,不能选同一个中转点,有些点相互LOVE,必需选相同中转点
(显然是2sat条件)。
关键:每次二分枚举limit,按limit建图,需要注意的是每条逻辑语句对应两条边(相互对称,逻辑上互为假言易位),
如:必需连通一个点,逻辑语句俩条:a->b,b->a,对应各自假言易位式,4条边。
相信二sat不再是问题了。
#include<iostream>//1200ms/2000ms 1A
#include<queue>
#include<stack>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
struct point
{
int x,y;
};
vector<vector<int> >e(1050);
int n,a,b;point s1,s2; int maxdis=4000001;
point po[505]; point hate[1005]; point love[1005];
int absint(int x)
{
if(x<0)return -x;
return x;
}
int dis(point aa,point bb) //距离
{
return absint(aa.x-bb.x)+absint(aa.y-bb.y);
}
void build(int limit) //每次二分后建图
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) //注意不要加ELSE
{
if(i==j)continue;
if((dis(po[i],s1)+dis(po[j],s2)+dis(s1,s2))>limit) //无法到达了,
{
e[2*i-1].push_back(2*j-1);
e[2*j-2].push_back(2*i-2);
}
if((dis(po[i],s1)+dis(po[j],s1))>limit)
{
e[2*i-1].push_back(2*j-2);
e[2*j-1].push_back(2*i-2);
}
if((dis(po[i],s2)+dis(po[j],s2))>limit)
{
e[2*i-2].push_back(2*j-1);
e[2*j-2].push_back(2*i-1);
}
}
for(int i=0;i<a;i++) //相互憎恨的
{
e[hate[i].x*2-1].push_back(hate[i].y*2-2);
e[hate[i].y*2-1].push_back(hate[i].x*2-2);
e[hate[i].x*2-2].push_back(hate[i].y*2-1);
e[hate[i].y*2-2].push_back(hate[i].x*2-1);
}
for(int i=0;i<b;i++) //相互喜爱的
{
e[love[i].x*2-1].push_back(love[i].y*2-1);
e[love[i].y*2-2].push_back(love[i].x*2-2);
e[love[i].y*2-1].push_back(love[i].x*2-1);
e[love[i].x*2-2].push_back(love[i].y*2-2);
}
}
int vis[1050];int dfn[1050];int low[1050];bool instack[1050];int block[1050];
int times=0; stack<int>s; int num=0;
void tarjan(int u) //下边是2sat缩点判断可行
{
dfn[u]=low[u]=++times;
instack[u]=1;
s.push(u);
int len=e[u].size();
for(int i=0;i<len;i++)
{
int v=e[u][i];
if(!vis[v])
{
vis[v]=1;
tarjan(v);
if(low[u]>low[v])low[u]=low[v];
}
else if(instack[v]&&dfn[v]<low[u])
low[u]=dfn[v];
}
if(dfn[u]==low[u])
{
num++;
int cur;
do{
cur=s.top();s.pop();
instack[cur]=0;
block[cur]=num;
}while(cur!=u);
}
}
bool check(int limit)
{
for(int i=0;i<=2*n-1;i++)
{
e[i].clear();
block[i]=vis[i]=dfn[i]=low[i]=instack[i]=0;
}
num=times=0;
build(limit);
for(int i=0;i<=2*n-1;i++)
if(!vis[i])
{
vis[i]=1;
tarjan(i);
}
for(int i=0;i<=2*n-1;i+=2)
if(block[i]==block[i+1])
return 0;
return 1;
}
int main()
{
scanf("%d%d%d",&n,&a,&b);scanf("%d%d%d%d",&s1.x,&s1.y,&s2.x,&s2.y);
for(int i=1;i<=n;i++)
scanf("%d%d",&po[i].x,&po[i].y);
for(int i=0;i<a;i++)
scanf("%d%d",&hate[i].x,&hate[i].y);
for(int i=0;i<b;i++)
scanf("%d%d",&love[i].x,&love[i].y);
int right=maxdis,left=0,mid;
if(!check(maxdis)){printf("-1\n");return 0;}
while(right>left+1)
{
mid=(right+left)/2;
if(check(mid))
{
right=mid;
}
else
left=mid;
}
if(check(right-1))printf("%d\n",right-1);
else printf("%d\n",right);
return 0;
}
POJ 2749 2SAT判定+二分的更多相关文章
- poj 2749 2-SAT问题
思路:首先将hate和friend建边求其次2-SAT问题,判断是否能有解,没解就输出-1,否则用二分枚举最大的长度,将两个barn的距离小于mid的看做是矛盾,然后建边,求2-SAT问题.找出最优解 ...
- poj 2723 二分+2-sat判定
题意:给出n对钥匙,每对钥匙只能选其中一个,在给出每层门需要的两个钥匙,只要一个钥匙就能开门,问最多能到哪层. 思路:了解了2-SAT判定的问题之后主要就是建图的问题了,这里建图就是对于2*n个钥匙, ...
- HDU 1815, POJ 2749 Building roads(2-sat)
HDU 1815, POJ 2749 Building roads pid=1815" target="_blank" style="">题目链 ...
- POJ 3111 K Best ( 二分 )
题意 : 给出 N 个物品的价值和重量,然后要求选出 K 个物品使得选出来物品的单位重量价值最大,最后输出被选物品的编号. 分析 : 很容易去想先算出每个物品的单位价值然后升序排序取前 K 个,但是 ...
- POJ 3273 Monthly Expense二分查找[最小化最大值问题]
POJ 3273 Monthly Expense二分查找(最大值最小化问题) 题目:Monthly Expense Description Farmer John is an astounding a ...
- Java实现 POJ 2749 分解因数(计蒜客)
POJ 2749 分解因数(计蒜客) Description 给出一个正整数a,要求分解成若干个正整数的乘积,即a = a1 * a2 * a3 * - * an,并且1 < a1 <= ...
- poj 2749 Building roads (二分+拆点+2-sat)
Building roads Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 6229 Accepted: 2093 De ...
- POJ 2749 Building roads 2-sat+二分答案
把爱恨和最大距离视为限制条件,可以知道,最大距离和限制条件多少具有单调性 所以可以二分最大距离,加边+check #include<cstdio> #include<algorith ...
- ZOJ 3717 二分+2-sat判定。
好久没有2-sat了,此题当复习之用,二分求最大值+2-sat判断可行,此题主要跪于题意:The results should be rounded to three decimal places. ...
随机推荐
- Knockout-了解Observable与computed
KO是什么? KO不是万能的,它的出现主要是为了方便的解决下面的问题: UI元素较多,用户交互比较频繁,需要编写大量的手工代码维护UI元素的状态.样式等属性? UI元素之间关系比较紧密,比如操作一个元 ...
- ZigBee cc2530芯片学习 error记录(1)
ZigBee cc2530芯片学习 error记录 Error[e46]: Undefined external "LcdInit" referred in main( xxx ...
- Java递归调用改成非递归
在java语言中,使用递归调用时,如果过多的调用容易造成java.lang.StackOverflowError即栈溢出和程序执行过慢.这是一个潜在Bug和影响程序执行效率问题,需要谨慎使 ...
- Tomcat7的安装与配置
Tomcat的安装及配置我曾经使用过tomcat,并实现了一个简单的servlet程序.没想到再次安装tomcat的时候用浪费了我大半天的时间.我想有必要做个总结,否则下次不知又要花费我多少时间. 1 ...
- 洛谷P1724 东风谷早苗
题目描述 在幻想乡,东风谷早苗是以高达控闻名的高中生宅巫女.某一天,早苗终于入手了最新款的钢达姆模型.作为最新的钢达姆,当然有了与以往不同的功能了,那就是它能够自动行走,厉害吧(好吧,我自重).早苗的 ...
- 洛谷 大牛分站 P1000 超级玛丽游戏
题目背景 本题是洛谷的试机题目,可以帮助了解洛谷的使用. 建议完成本题目后继续尝试P1001.P1008. 题目描述 超级玛丽是一个非常经典的游戏.请你用字符画的形式输出超级玛丽中的一个场景. *** ...
- 枚举 || CodeForces 742B Arpa’s obvious problem and Mehrdad’s terrible solution
给出N*M矩阵,对于该矩阵有两种操作: 1.交换两列,对于整个矩阵只能操作一次 2.每行交换两个数. 交换后是否可以使每行都递增. *解法:N与M均为20,直接枚举所有可能的交换结果,进行判断 每次枚 ...
- HTTP请求头的具体含意
为你详细解读HTTP请求头的具体含意 | 浏览:5763 | 更新:2012-03-16 16:41 当我们打开一个网页时,浏览器要向网站服务器发送一个HTTP请求头,然后网站服务器根据HTTP请求头 ...
- IOS学习笔记1—Iphone程序运行流程
Iphone程序运行流程 main.m文件,iOS应用程序的主入口 main函数的两个参数为命令行参数,在ios开发中不会用到这些元素,包括这两个参数是为了与标准ANSI C保持一致 UIApplic ...
- Linux 之 nano 编辑器的使用
在Linux操作系统中,有很多的文本编辑器,最为重要的就是vi文本编辑器,下面来介绍一个简单的nano文本编辑器.nano的使用简单,我们可以直接加上文件名就能够打开一个旧文件或新文件,我们可以打开一 ...