hdu1815 2sat + 二分 + 建图
题意:
给你两个总部,s1 ,s2,和n个点,任意两点之间都是通过这个总部相连的,其中有一些点不能连在同一个总部上,有一些点可以连接在同一个总部上,总部和总部之间可以直接连接,就是假如a,b相连,可以使这样四中情况中的一种
a-s1 s1 - b
a-s2 s2 - b
a-s1 s1 - s2 s2 - b
a-s2 s2 - s1 s1 - b
最后问你任意ab距离最远的最近是多少。
思路:
首先这个题目的总部有两个,还有一些限制关系,那么很容易就想到2sat问题,关键是怎么建边,怎样找到限制关系,还是举例子说容易懂,
s_x1[i] : 表示i点到S1的距离。
s_x2[i] : 表示i点到S2的距离。
D 表示S1,S2的距离。
彼此厌恶 x -> ~y ,y -> ~x ,~y -> x ,~x -> y
彼此喜欢 x -> y ,~x -> ~y ,y -> x ,~y -> ~x
s_x1[x] + s_x1[y] > mid x -> ~y ,y -> ~x
s_x2[x] + s_x2[y] > mid ~x -> y ,~y -> x
s_x1[x] + s_x2[y] + D > mid x -> y ,~y -> ~x
s_x2[x] + s_x1[y] + D > mid ~x -> ~y ,y -> x
每次二分就这么建边就ok了,还有提示下,之前在网上看到有个人的题解是直接先跑了便彼此厌恶和喜欢的,然后二分的时候就不管那个了,那个我感觉正确性说不通,我是每次都全部从新建边的,上面的如果写错了请大家留言指教,互相学习。
#include<stdio.h>
#include<string.h>
#include<stack> #define N_node 1000 + 10
#define N_edge 5000000 + 300
using namespace std; typedef struct
{
int to ,next;
}STAR; typedef struct
{
int x ,y;
}NODE; STAR E1[N_edge] ,E2[N_edge];
NODE S1 ,S2 ,A;
int s_x1[550] ,s_x2[550];
int list1[N_node] ,list2[N_node] ,tot;
int Belong[N_node] ,cnt;
int mark[N_node];
int F[1100][2] ,NF[1100][2];
stack<int>st; void add(int a ,int b)
{
E1[++tot].to = b;
E1[tot].next = list1[a];
list1[a] = tot; E2[tot].to = a;
E2[tot].next = list2[b];
list2[b] = 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);
} int abss(int x)
{
return x > 0 ? x : -x;
} int dis(NODE a ,NODE b)
{
return abss(a.x - b.x) + abss(a.y - b.y);
} bool ok(int mid ,int n ,int m ,int q)
{
memset(list1 ,0 ,sizeof(list1));
memset(list2 ,0 ,sizeof(list2));
tot = 1;
for(int i = 1 ;i <= m ;i ++)
{
int x = NF[i][0] * 2 ,xx = NF[i][0] * 2 + 1;
int y = NF[i][1] * 2 ,yy = NF[i][1] * 2 + 1;
add(x ,yy) ,add(y ,xx);
add(yy ,x) ,add(xx ,y);
}
for(int i = 1 ;i <= q ;i ++)
{
int x = F[i][0] * 2 ,xx = F[i][0] * 2 + 1;
int y = F[i][1] * 2 ,yy = F[i][1] * 2 + 1;
add(x ,y) ,add(xx ,yy);
add(y ,x) ,add(yy ,xx);
}
int D = dis(S1 ,S2);
for(int i = 0 ;i < n ;i ++)
for(int j = i + 1 ;j < n ;j ++)
{
int x = i * 2 ,xx = i * 2 + 1;
int y = j * 2 ,yy = j * 2 + 1;
if(s_x1[i] + s_x1[j] > mid) add(x ,yy) ,add(y ,xx);
if(s_x2[i] + s_x2[j] > mid) add(xx ,y) ,add(yy ,x);
if(s_x1[i] + s_x2[j] + D > mid) add(x ,y) ,add(yy ,xx);
if(s_x2[i] + s_x1[j] + D > mid) add(xx ,yy) ,add(y ,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 n ,m ,q;
int i ,low ,mid ,up;
while(~scanf("%d %d %d" ,&n ,&m ,&q))
{
scanf("%d %d %d %d" ,&S1.x ,&S1.y ,&S2.x ,&S2.y);
low = up = 8000000;
for(i = 0 ;i < n ;i ++)
{
scanf("%d %d" ,&A.x ,&A.y);
s_x1[i] = dis(A ,S1);
s_x2[i] = dis(A ,S2);
if(low > s_x1[i]) low = s_x1[i];
if(low > s_x2[i]) low = s_x2[i];
}
for(i = 1 ;i <= m ;i ++)
{
scanf("%d %d" ,&NF[i][0] ,&NF[i][1]);
NF[i][0] -- ,NF[i][1] --;
}
for(i = 1 ;i <= q ;i ++)
{
scanf("%d %d" ,&F[i][0] ,&F[i][1]);
F[i][0] -- ,F[i][1] -- ;
}
int ans = -1;
while(low <= up)
{
mid = (low + up) >> 1;
if(ok(mid ,n ,m ,q))
ans = mid ,up = mid - 1;
else low = mid + 1;
}
printf("%d\n" ,ans);
}
return 0;
}
hdu1815 2sat + 二分 + 建图的更多相关文章
- 关于2-sat的建图方法及解决方案
转载增减: https://blog.csdn.net/qq_24451605/article/details/47126143 https://blog.csdn.net/u012915516/ar ...
- P3355 骑士共存问题 二分建图 + 当前弧优化dinic
P3355 骑士共存问题 题意: 也是一个棋盘,规则是“马”不能相互打到. 思路: 奇偶点分开,二分图建图,这道题要注意每个点可以跑八个方向,两边都可以跑,所以边 = 20 * n * n. 然后di ...
- HDU1815 2-sat+二分
Building roads Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...
- [poj 3678]Katu Pazzle[2-SAT常用建图法]
题意: 不说了..典型的2-SAT 常用模型: 重点: 突出"绑定性". 连线表示限制而非可行. 因为最后要求对立点不在同一强连通分量是说同一强连通中的点必须同时选. 坑: 首先是 ...
- hdu3715 二分+2sat+建图
题意: 给你一个递归公式,每多一层就多一个限制,问你最多能递归多少层. 思路: 先分析每一层的限制 x[a[i]] + x[b[i]] != c[i],这里面x[] = 0,1, ...
- 【ARC069F】Flags 2-sat+线段树优化建图+二分
Description 数轴上有 n 个旗子,第 ii 个可以插在坐标 xi或者 yi,最大化两两旗子之间的最小距离. Input 第一行一个整数 N. 接下来 N 行每行两个整数 xi, ...
- Codeforces 587D - Duff in Mafia(2-SAT+前后缀优化建图)
Codeforces 题面传送门 & 洛谷题面传送门 2-SAT hot tea. 首先一眼二分答案,我们二分答案 \(mid\),那么问题转化为,是否存在一个所有边权都 \(\le mid\ ...
- BZOJ-1822 Frozen Nova 冷冻波 计(jie)算(xi)几何+二分+最大流判定+经典建图
这道逼题!感受到了数学对我的深深恶意(#‵′).... 1822: [JSOI2010]Frozen Nova 冷冻波 Time Limit: 10 Sec Memory Limit: 64 MB S ...
- BZOJ-1305 dance跳舞 建图+最大流+二分判定
跟随YveH的脚步又做了道网络流...%%% 1305: [CQOI2009]dance跳舞 Time Limit: 5 Sec Memory Limit: 162 MB Submit: 2119 S ...
随机推荐
- Thinkphp3分析与审计
0x00 前言: 这篇是去年组内分享的时候给小伙伴写的0基础快速审计tp3系列的文章,主要是对架构做个分析以及审计一些sql注入漏洞~ 现在想想打算放出来,过了一年了,可能里面有一些问题,望看到的大佬 ...
- 关闭ubuntu防火墙
1.关闭ubuntu的防火墙 ufw disable 开启防火墙 ufw enable 2.卸载了iptables apt-get remove iptables 3.关闭ubuntu中的防火墙的其余 ...
- WPF 基础 - 绘画 1) 线段、矩形、圆弧及填充色
1. 绘画 1.1 图形类型 Line X1.Y1.X2.Y2,Stroke,StrokeThickness Rectangle 矩形 Ellipse 椭圆 Polygon 多边形(自动闭合) Pol ...
- Linux less命令查看文件常用查询方法
g 跳到文件开头 G 跳到文件结尾 / 往下搜索字符 ? 网上搜索字符 n 执行上一个搜索(/或者?的搜索),例如上一个搜索是使用/搜索的,则继续使用/搜索,即往下搜索结果 N 反向执行上一个搜索(/ ...
- python-for表达式
for表达式用于其他区间,元组,列表等可迭代对象创建新的列表 [表达式 for 循环计数器 in 可迭代对象] for表达式与普通for循环的区别有两点 在for关键字之前定义一个表达式,该表达式通常 ...
- gsoap多wsdl集成
gsoap常规用法: 通过wsdl文件创建头文件 //通过wsdl文件创建头文件 wsdl2h [options] -o file.h ... WSDL and XSD files or URLs t ...
- codefoces B - Phoenix and Beauty
原题链接:https://codeforc.es/problemset/problem/1348/B 题意:告诉我们一个数组及其长度和k,判断是否可以构造一个新数组使得每K段长度和都相等. 思路:首先 ...
- P1149_火柴棒等式(JAVA语言)
题目描述 给你n根火柴棍,你可以拼出多少个形如"A+B=C"的等式?等式中的A.B.C是用火柴棍拼出的整数(若该数非零,则最高位不能是0).用火柴棍拼数字0-90−9的拼法如图所示 ...
- 创建Maven父子项目以及它们的优点
此文引用:https://blog.csdn.net/zxl8876/article/details/104180133 创建maven父子项目 第一步创建父项目: 新建一个普通的maven项目 删除 ...
- 第4 章 : 理解 Pod 和容器设计模式
理解Pod和容器设计模式 本文整理自 CNCF 和阿里巴巴联合举办的云原生技术公开课的课时 4:理解 Pod 和容器设计模式.本次课程中,阿阿里巴巴高级技术专家.CNCF 官方大使张磊为大家介绍了为什 ...