Building roads

Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1569    Accepted Submission(s): 490

Problem Description

Farmer John's farm has N barns, and there are some cows that live in each barn. The cows like to drop around, so John wants to build some roads to connect these barns. If he builds roads for every pair of different barns, then he must build N * (N - 1) / 2 roads, which is so costly that cheapskate John will never do that, though that's the best choice for the cows.

Clever John just had another good idea. He first builds two transferring point S1 and S2, and then builds a road connecting S1 and S2 and N roads connecting each barn with S1 or S2, namely every barn will connect with S1 or S2, but not both. So that every pair of barns will be connected by the roads. To make the cows don't spend too much time while dropping around, John wants to minimize the maximum of distances between every pair of barns.

That's not the whole story because there is another troublesome problem. The cows of some barns hate each other, and John can't connect their barns to the same transferring point. The cows of some barns are friends with each other, and John must connect their barns to the same transferring point. What a headache! Now John turns to you for help. Your task is to find a feasible optimal road-building scheme to make the maximum of distances between every pair of barns as short as possible, which means that you must decide which transferring point each barn should connect to.

We have known the coordinates of S1, S2 and the N barns, the pairs of barns in which the cows hate each other, and the pairs of barns in which the cows are friends with each other.

Note that John always builds roads vertically and horizontally, so the length of road between two places is their Manhattan distance. For example, saying two points with coordinates (x1, y1) and (x2, y2), the Manhattan distance between them is |x1 - x2| + |y1 - y2|.

 

Input

The first line of input consists of 3 integers N, A and B (2 <= N <= 500, 0 <= A <= 1000, 0 <= B <= 1000), which are the number of barns, the number of pairs of barns in which the cows hate each other and the number of pairs of barns in which the cows are friends with each other.

Next line contains 4 integer sx1, sy1, sx2, sy2, which are the coordinates of two different transferring point S1 and S2 respectively.

Each of the following N line contains two integer x and y. They are coordinates of the barns from the first barn to the last one.

Each of the following A lines contains two different integers i and j(1 <= i < j <= N), which represent the i-th and j-th barns in which the cows hate each other.

The same pair of barns never appears more than once.

Each of the following B lines contains two different integers i and j(1 <= i < j <= N), which represent the i-th and j-th barns in which the cows are friends with each other. The same pair of barns never appears more than once.

You should note that all the coordinates are in the range [-1000000, 1000000].

 

Output

You just need output a line containing a single integer, which represents the maximum of the distances between every pair of barns, if John selects the optimal road-building scheme. Note if there is no feasible solution, just output -1. 
 

Sample Input

4 1 1
12750 28546 15361 32055
6706 3887
10754 8166
12668 19380
15788 16059
3 4
2 3
 

Sample Output

53246
 

Source

 

思路:二分枚举最大值limit,然后重新构图,用2-SAT判定可行性。用Xi表示第i个牛棚连到S1,~Xi表示连到S2,检查每一个约束条件,构图:

1.hate关系的i,j Xi->~Xj ~Xi->Xj Xj->~Xi ~Xj->Xi
2.friend关系的i,j Xi->Xj ~Xi->~Xj Xj->Xi ~Xj->~Xi
接下来的也要检查,因为引入参数,就是多了约束条件了
这四种情况就是i,j到达对方的所有情况了
3.dist(i,S1)+dist(S1,j)>limit Xi->~Xj Xj->Xi
4.dist(i,S2)+dist(S2,j)>limit ~Xi->Xj ~Xj->Xi
5.dist(i,S1)+dist(S1,S2)+dist(S2,j)>limit Xi->Xj ~Xj->~Xi
5.dist(i,S2)+dist(S2,S1)+dist(S1,j)>limit ~Xi->~Xj Xj->Xi

然后求强连通分量判断Xi与~Xi是否在同一个连通分量中,是的话就有矛盾。

 //2017-08-28
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath> using namespace std; const int N = ;
const int M = N*N*;
int head[N], rhead[N], tot, rtot;
struct Edge{
int to, next;
}edge[M], redge[M]; void init(){
tot = ;
rtot = ;
memset(head, -, sizeof(head));
memset(rhead, -, sizeof(rhead));
} void add_edge(int u, int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++; redge[rtot].to = u;
redge[rtot].next = rhead[v];
rhead[v] = rtot++;
} vector<int> vs;//后序遍历顺序的顶点列表
bool vis[N];
int cmp[N];//所属强连通分量的拓扑序 //input: u 顶点
//output: vs 后序遍历顺序的顶点列表
void dfs(int u){
vis[u] = true;
for(int i = head[u]; i != -; i = edge[i].next){
int v = edge[i].to;
if(!vis[v])
dfs(v);
}
vs.push_back(u);
} //input: u 顶点编号; k 拓扑序号
//output: cmp[] 强连通分量拓扑序
void rdfs(int u, int k){
vis[u] = true;
cmp[u] = k;
for(int i = rhead[u]; i != -; i = redge[i].next){
int v = redge[i].to;
if(!vis[v])
rdfs(v, k);
}
} //Strongly Connected Component 强连通分量
//input: n 顶点个数
//output: k 强连通分量数;
int scc(int n){
memset(vis, , sizeof(vis));
vs.clear();
for(int u = ; u < n; u++)
if(!vis[u])
dfs(u);
int k = ;
memset(vis, , sizeof(vis));
for(int i = vs.size()-; i >= ; i--)
if(!vis[vs[i]])
rdfs(vs[i], k++);
return k;
} int n, A, B, dis_s1[N], dis_s2[N], dis_s1_s2;
struct Point{
int x, y;
}point[N], s1, s2, hate[N], friends[N]; //input: 两个点
//output: 两点间距离
double distance(Point a, Point b){
return abs(a.x-b.x) + abs(a.y-b.y);
} bool check(int limit){
init();
// i 表示 i 连 s1, NOT i 表示 i 连 s2
for(int i = ; i < n; i++){
bool fg = true;
if(distance(point[i], s1) > limit){
add_edge(i, i+n);
fg = false;
}
if(distance(point[i], s2) > limit){
if(!fg)return false;
add_edge(i+n, i);
}
for(int j = i+; j < n; j++){
if(dis_s1[i] + dis_s1[j] > limit){
add_edge(i, j+n);// i -> s1, j -> s2
add_edge(j, i+n);// j -> s1, i -> s2
}
if(dis_s2[i] + dis_s2[j] > limit){
add_edge(i+n, j);// i -> s2, j -> s1
add_edge(j+n, i);// j -> s2, i -> s1
}
if(dis_s1[i] + dis_s1_s2 + dis_s2[j] > limit){
add_edge(i, j);// i -> s1, j -> s1
add_edge(j+n, i+n);// j -> s2, i -> s2
}
if(dis_s2[i] + dis_s1_s2 + dis_s1[j] > limit){
add_edge(i+n, j+n);// i -> s2, j -> s2
add_edge(j, i);// j -> s1, i -> s1
}
}
}
for(int i = ; i < A; i++){
int u = hate[i].x, v = hate[i].y;
add_edge(u, v+n);
add_edge(v+n, u);
add_edge(v, u+n);
add_edge(u+n, v);
}
for(int i = ; i < B; i++){
int u = friends[i].x, v = friends[i].y;
add_edge(u, v);
add_edge(v, u);
add_edge(u+n, v+n);
add_edge(v+n, u+n);
}
scc(*n);
for(int i = ; i < n; i++){
if(cmp[i] == cmp[i+n])
return false;
}
return true;
} int main()
{
std::ios::sync_with_stdio(false);
//freopen("inputE.txt", "r", stdin);
while(cin>>n>>A>>B){
cin>>s1.x>>s1.y>>s2.x>>s2.y;
dis_s1_s2 = distance(s1, s2);
for(int i = ; i < n; i++){
cin>>point[i].x>>point[i].y;
dis_s1[i] = distance(point[i], s1);
dis_s2[i] = distance(point[i], s2);
}
for(int i = ; i < A; i++){
cin>>hate[i].x>>hate[i].y;
hate[i].x--;
hate[i].y--;
}
for(int i = ; i < B; i++){
cin>>friends[i].x>>friends[i].y;
friends[i].x--;
friends[i].y--;
}
//r 开小了HDU会TLE,ORZ。。。
int l = , r = , mid, ans = -;
while(l <= r){
mid = (l+r)/;
if(check(mid)){
ans = mid;
r = mid-;
}else l = mid+;
}
cout<<ans<<endl;
}
return ;
}

HDU1815(二分+2-SAT)的更多相关文章

  1. HDU1815 2-sat+二分

    Building roads Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...

  2. hdu1815 2sat + 二分 + 建图

    题意:       给你两个总部,s1 ,s2,和n个点,任意两点之间都是通过这个总部相连的,其中有一些点不能连在同一个总部上,有一些点可以连接在同一个总部上,总部和总部之间可以直接连接,就是假如a, ...

  3. HDU1815 Building roads(二分+2-SAT)

    Problem Description Farmer John's farm has N barns, and there are some cows that live in each barn. ...

  4. 证明与计算(3): 二分决策图(Binary Decision Diagram, BDD)

    0x01 布尔代数(Boolean algebra) 大名鼎鼎鼎的stephen wolfram在2015年的时候写了一篇介绍George Boole的文章:George Boole: A 200-Y ...

  5. Map Labeler POJ - 2296(2 - sat 具体关系建边)

    题意: 给出n个点  让求这n个点所能建成的正方形的最大边长,要求不覆盖,且这n个点在正方形上或下边的中点位置 解析: 当然是二分,但建图就有点还行..比较难想..行吧...我太垃圾... 2 - s ...

  6. LA 3211 飞机调度(2—SAT)

    https://vjudge.net/problem/UVALive-3211 题意: 有n架飞机需要着陆,每架飞机都可以选择“早着陆”和“晚着陆”两种方式之一,且必须选择一种,第i架飞机的早着陆时间 ...

  7. UVALive - 3211 (2-SAT + 二分)

    layout: post title: 训练指南 UVALive - 3211 (2-SAT + 二分) author: "luowentaoaa" catalog: true m ...

  8. hdu3715 2-sat+二分

    Go Deeper 题意:确定一个0/1数组(size:n)使得满足最多的条件数.条件在数组a,b,c给出. 吐槽:哎,一水提,还搞了很久!关键是抽象出题目模型(如上的一句话).以后做二sat:有哪些 ...

  9. POJ 2749 2SAT判定+二分

    题意:图上n个点,使每个点都与俩个中转点的其中一个相连(二选一,典型2-sat),并使任意两点最大 距离最小(最大最小,2分答案),有些点相互hata,不能选同一个中转点,有些点相互LOVE,必需选相 ...

随机推荐

  1. Python大黑阔—url采集+exp验证,带你批量测试

    i春秋作家:大木瓜 前言: 最近几天在整理从各处收集来的各种工具包,大大小小的塞满了十几个G的硬盘,无意间发现了一个好几年前的0day.心血来潮就拿去试了一下,没想到真的还可以用,不过那些站点都已经老 ...

  2. ssh免密码登录Permission denied (publickey,gssapi-keyex,gssapi-with-mic) 的解决方案!

    当出现Permission denied (publickey,gssapi-keyex,gssapi-with-mic) 警告的时候,恭喜你,你已经离成功很近了. 远程主机这里设为slave2,用户 ...

  3. jvm垃圾回收的过程

    垃圾回收的过程分为两步: 1.判断对象是否死亡 (1)引用计数器法: ①每当有一个对象引用是,计数器加一,当计数器为0是对象死亡 ②缺点:无法解决循环引用的问题,假设A引用B,B引用A,那么这两个对象 ...

  4. JS 跨域认识及如何解决

    什么是跨域 指的是浏览器不允许javascrip脚本向其他域名发起ajax请求. 跨域的各种情况判定 URL 说明 是否允许通信 http://www.a.com/a.js http://www.a. ...

  5. [原创]K8_C段旁注工具6.0 新增SMB漏洞扫描

    工具: K8_C段旁注工具6.0_0510[K.8]编译: 自己查壳组织: K8搞基大队[K8team]作者: K8拉登哥哥博客: http://qqhack8.blog.163.com发布: 201 ...

  6. BIND DNS拒绝服务漏洞 CVE-2016-2776修复

    接到此漏洞之后,略微查了一下相关描述,发现漏洞影响范围很大,可能造成的影响也很严重,于是着手进行修复. 漏洞的详细信息可见如下链接: http://www.cnvd.org.cn/flaw/show/ ...

  7. WebForm - cookie赋值乱码问题

    cookie的值为中文时候,取cookie的值会出现乱码 解决办法:存取cookie时候先解码和编码 存cookie,进行编码: cookie.Value = HttpUtility.UrlEncod ...

  8. vue教程2-04 vue实例简单方法

    vue教程2-04 vue实例简单方法 vue实例简单方法: vm.$el -> 就是元素 vm.$data -> 就是data <!DOCTYPE html> <htm ...

  9. winform计算文本的所占的像素长度

    /// <summary> /// 计算文本的宽度 /// </summary> /// <param name="str"></para ...

  10. 课程一(Neural Networks and Deep Learning),第二周(Basics of Neural Network programming)—— 0、学习目标

    1. Build a logistic regression model, structured as a shallow neural network2. Implement the main st ...