题目大意:有若干牛圈和两个连接起来的的中转点S1,S2。每个牛圈需要选择其中一个中转点与之连接,从而使任意两个牛圈能够连通。有若干对牛圈里的牛互相hate或是互相like。若两个牛圈里的牛互相hate,就不能连接到同一个中转点上,而如果互相like,就必须连接到同一个中转点上。连接方案还要使两个牛圈之间的距离的最大值尽可能小,并求出这个值。

思路:2-SAT+二分,对每个牛圈x,令x为与S1连接,¬x为与S2连接。接下来,对于每对互相hate的奶牛所在的牛圈a,b不能连接到同一个中转点上,所以连边(a,¬b),(¬b,a),(b,¬a),(¬a,b),对于每对互相like的奶牛所在的牛圈a,b必须连接到同一个中转点上,所以连边(a,b),(b,a),(¬a,¬b),(¬b,¬a)。之后要让所有连接起来的牛圈之间的距离的最大值尽量小,可以用二分,对每个距离,枚举所有相互连接的牛圈,牛圈(a,b)之间的连接方式又可以分为4种情况:

1)都连接在S1上

2)都连接在S2上

3)a连接在S1上并且b连接在S2上

4)a连接在S2上并且b连接在S1上

如果哪种连接方式使a,b的距离大于当前距离,就加边来限制这种连接。对于情况1),就连边(a,¬b)和(b,¬a)情况2)类似地去连边(¬a,b)和(¬b,a),对于情况3)就连边(a,b)和(¬b,¬a)情况4)类似地去连边(b,a)和(¬a,¬b)

最后如果二分没能找到结果就说明无法连接。

代码如下:

//POJ.2749
//Author: Prgl
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0) typedef pair<int, int>P;
typedef vector<int>vec; #define INF 0x3f3f3f3f
const double EPS = 1e-18;
const int MOD = 1e9 + 7;
const int maxv = 1001;
const int maxn = 501; int V;
vec G[maxv], rG[maxv];
stack<int>s;
bool used[maxv];
int cmp[maxv]; int N, A, B;
int sx1, sy1, sx2, sy2, D;
int X[maxn], Y[maxn];
P a[maxn], b[maxn];
int d1[maxn], d2[maxn], d[maxn];
bool one[maxn]; inline void add_edge(int from, int to)
{
G[from].push_back(to);
rG[to].push_back(from);
} void add_edge_hate(int from, int to)
{
add_edge(from, to + N);
add_edge(to, from + N);
add_edge(from + N, to);
add_edge(to + N, from);
} void add_edge_like(int from, int to)
{
add_edge(from + N, to + N);
add_edge(to + N, from + N);
add_edge(from, to);
add_edge(to, from);
} inline int dis(int x1, int y1, int x2, int y2)
{
return abs(x1 - x2) + abs(y1 - y2);
} void dfs(int v)
{
used[v] = true;
for (int i = 0; i < G[v].size(); i++)
{
if (!used[G[v][i]])
dfs(G[v][i]);
}
s.push(v);
} void rdfs(int v, int k)
{
cmp[v] = k;
used[v] = true;
for (int i = 0; i < rG[v].size(); i++)
{
if (!used[rG[v][i]])
rdfs(rG[v][i], k);
}
} int scc()
{
memset(used, 0, sizeof(used));
for (int v = 0; v < V; v++)
{
if (!used[v])
dfs(v);
}
memset(used, 0, sizeof(used));
int k = 0;
while (!s.empty())
{
int v = s.top();
s.pop();
if (!used[v])
rdfs(v, k++); } return k;
} bool C(int md)
{
for (int i = 0; i < V; i++)
{
G[i].clear();
rG[i].clear();
}
for (int i = 0; i < A; i++)
{
int u = a[i].first - 1, v = a[i].second - 1;
add_edge_hate(u, v);
}
for (int i = 0; i < B; i++)
{
int u = b[i].first - 1, v = b[i].second - 1;
add_edge_like(u, v);
}
for (int i = 0; i < N - 1; i++)
{
for (int j = i + 1; j < N; j++)
{
if (d1[i] + d1[j] > md)
{
add_edge(i, j + N);
add_edge(j, i + N);
}
if (d2[i] + d2[j] > md)
{
add_edge(j + N, i);
add_edge(i + N, j);
}
if (D + d1[i] + d2[j] > md)
{
add_edge(i, j);
add_edge(j + N, i + N);
}
if (D + d2[i] + d1[j] > md)
{
add_edge(j, i);
add_edge(i + N, j + N);
}
}
}
scc();
for (int i = 0; i < N; i++)
{
if (cmp[i] == cmp[i + N])
return false;
} return true;
} void solve()
{
V = N * 2;
D = dis(sx1, sy1, sx2, sy2);
for (int i = 0; i < N; i++)
{
d1[i] = dis(X[i], Y[i], sx1, sy1);
d2[i] = dis(X[i], Y[i], sx2, sy2);
}
int lo = -1, hi = 12000001;
while (hi - lo > 1)
{ int mi = (hi + lo) / 2;
if (C(mi))
hi = mi;
else
lo = mi;
}
if (lo == 12000000)
cout << -1 << endl;
else
cout << hi << endl;
} int main()
{
IOS;
cin >> N >> A >> B;
cin >> sx1 >> sy1 >> sx2 >> sy2;
for (int i = 0; i < N; i++)
cin >> X[i] >> Y[i];
for (int i = 0; i < A; i++)
{
int u, v;
cin >> u >> v;
a[i] = P(u, v);
}
for (int i = 0; i < B; i++)
{
int u, v;
cin >> u >> v;
b[i] = P(u, v);
}
solve(); return 0;
}

POJ2749 题解的更多相关文章

  1. POJ2749:Building roads——题解

    http://poj.org/problem?id=2749 (这个约翰的奶牛真多事…………………………) i表示u与s1连,i+n表示u与s2连. 老规矩,u到v表示取u必须取v. 那么对于互相打架 ...

  2. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  3. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  4. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  5. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  6. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  7. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  8. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  9. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

随机推荐

  1. Python小练习更改版(更改一部分代码,与错误)

    之前上传的发现有部分代码错误,重新上传: 更改了第一次的代码与错误,增加了注释与商店部分功能: 没有每天坚持更新博客,与初衷相差甚远,坚持!每天进步一点点! user_list.txt 部分代码: { ...

  2. mac 更新到big sur 后,parallels虚拟机的一些问题:由于您尚未获得访问其中一些文件的授权,所以您不能恢复“Windows 10

    由于您尚未获得访问其中一些文件的授权,所以您不能恢复"Windows 10 Mac上使用PD虚拟机,打开系统时提示"由于您尚未获得访问其中一些文件的授权,所以您不能恢复" ...

  3. JavaScript如何实现上拉加载,下拉刷新?

    转载地址: 面试官:JavaScript如何实现上拉加载,下拉刷新? 一.前言 下拉刷新和上拉加载这两种交互方式通常出现在移动端中 本质上等同于PC网页中的分页,只是交互形式不同 开源社区也有很多优秀 ...

  4. Django settings.py配置文件

    import os BASE_DIR = os.path.dirname(os.path.dirname(__file__)) 这里用到了python中一个神奇的变量 file 这个变量可以获取到当前 ...

  5. 什么是VPC

    1 什么是私有网络(VPC) 私有网络是一块可用户自定义的网络空间,您可以在私有网络内部署云主机.负载均衡.数据库.Nosql快存储等云服务资源.您可自由划分网段.制定路由策略.私有网络可以配置公网网 ...

  6. 第05讲:Flink SQL & Table 编程和案例

    Flink系列文章 第01讲:Flink 的应用场景和架构模型 第02讲:Flink 入门程序 WordCount 和 SQL 实现 第03讲:Flink 的编程模型与其他框架比较 第04讲:Flin ...

  7. 洛谷P1060 java题解

    题目描述: 解题思路: 重要度相当于价值的倍率 (物品价格*重要度=价值) 经典的背包问题 直接DP把各种情况下的最优解打表出来取最后一个就行了 代码: import java.util.Scanne ...

  8. Programiz 中文系列教程·翻译完成

    原文:Programiz 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远. 在线阅读 ApacheCN 学习资源 目录 Programiz C ...

  9. 最长公共子序列-LIS

    题目描述 时间限制:1.0s 内存限制:256.0MB 问题描述 给定一个长为\(n\)的序列,求它的最长上升子序列的长度. 输入格式 输入第一行包含一个整数\(n\). 第二行包含\(n\)个整数\ ...

  10. springboot druid 数据库连接池连接失败后一直重连

    在使用个人阿里云测试机,在查询实时输出日志时,看到数据库连接失败后,服务器一直在重连服务器.开始以为是遭受重复攻击,后面把服务重启后,就没有出现一直重连的情况.看以下输出日志: 2022-02-09 ...