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 ...
随机推荐
- 摄像机+LookAt矩阵+视角移动+欧拉角
一: 摄像机 OpenGL本身没有摄像机(Camera)的概念,但我们可以通过把场景中的所有物体往相反方向移动的方式来模拟出摄像机,产生一种我们在移动的感觉,而不是场景在移动. 以摄像机的视角作为场景 ...
- 2020年12月-第02阶段-前端基础-CSS Day07
CSS Day07 CSS高级技巧 理解 能说出元素显示隐藏最常见的写法 能说出精灵图产生的目的 能说出去除图片底侧空白缝隙的方法 应用 能写出最常见的鼠标样式 能使用精灵图技术 能用滑动门做导航栏案 ...
- 如何在 C# 中使用 ArrayPool 和 MemoryPool
对资源的可复用是提升应用程序性能的一个非常重要的手段,比如本篇要分享的 ArrayPool 和 MemoryPool,它们就有效的减少了内存使用和对GC的压力,从而提升应用程序性能. 什么是 Arra ...
- SpringMVC自定义兼容性Handler
写在前面 看到这篇博客时,默认你知道Spring MVC中handler的作用,及前台请求到响应的的流转. 感谢网上其他大佬博客给我的借鉴,博客地址这里忘记了. 自定义Handler 我有时候会考虑是 ...
- Intellij IDEA实用插件Lombok
使用@Data注解后 可以不用给属性添加get.set方法也可以使用get.set方法,但是必须添加lombok Plugin插件 1 打开设置Setting,选中Plugins,搜索并安装Lombo ...
- python plt画图横纵坐标0点重合
# -*- coding: utf-8 -*- import numpy as np import matplotlib.mlab as mlab import matplotlib.pyplot a ...
- Mardown语法
1.什么是Markdown Mardown是一种文本标记语言,使用它,能让我们更加专注于内容的输出,而不是排版样式. 我们平常使用的.txt文档书写的文字是没有样式的,使用Markdown语法就可以给 ...
- python网络编程TCP服务多客户端的服务端开发
#服务多客户端TCP服务端开发 2 #方法说明 3 """ 4 bind(host,port)表示绑定端口号,host是ip地址,ip地址一般不进 行绑定,表示本机的任何 ...
- 浅析MyBatis(三):聊一聊MyBatis的实用插件与自定义插件
在前面的文章中,笔者详细介绍了 MyBatis 框架的底层框架与运行流程,并且在理解运行流程的基础上手写了一个自己的 MyBatis 框架.看完前两篇文章后,相信读者对 MyBatis 的偏底层原理和 ...
- 灵魂拷问!浏览器输入「xxxxhub」的背后.....
Hey guys 各位读者姥爷们大家好,这里是程序员 cxuan 计算机网络连载系列的第 13 篇文章. 到现在为止,我们算是把应用层.运输层.网络层和数据链路层都介绍完了,那么现在是时候把这些内容都 ...