题目大意:有若干牛圈和两个连接起来的的中转点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. Android开发----使用 Room 将数据保存到本地数据库

    Room介绍以及不使用SQLite的原因 Room 在 SQLite 上提供了一个抽象层,以便在充分利用 SQLite 的强大功能的同时,能够流畅地访问数据库. 处理大量结构化数据的应用可极大地受益于 ...

  2. python开发之函数

    转:https://www.tuicool.com/wx/vEVrqeR 06 python开发之函数 博客园精华区12-12 20:56 06 python开发之函数 目录 6.2 调用函数与函数返 ...

  3. ApacheCN JavaScript 译文集(二) 20211123 更新

    使用 Meteor 构建单页 Web 应用 零.前言 一.制作 Meteor 应用 二.构建 HTML 模板 三.存储数据和处理集合 四.控制数据流 五.使我们的应用与路由通用 六.保持会话状态 七. ...

  4. CEH v8~v11 Module Slides 和 Lab Manual 下载

    课程内容 CEH v8 01 Introduction to Ethical Hacking CEH v8 02 Footprinting and Reconnaissance CEH v8 03 S ...

  5. jdk、jre、javase、javaee、javame的区别

    Jdk定义 JAVA的开发工具包,包含jre,可以进行编译和运行Java程序. Jre定义 JAVA的运行环境,如果不需要进行编译程序,则可只安装jre. Javase定义 标准版Java SE(Ja ...

  6. Eclipse集成Git/SVN插件及使用

    感谢大佬:https://www.cnblogs.com/jpfss/p/8027347.html 1. Git插件安装 1.1 下载插件 首先打开Eclipse,然后点击Help>Instal ...

  7. 学习Java Web篇:MVC设计模式

    一.MVC设计模式 1.什么是MVC模式 1.1.MVC -- Model View Controller模型视图控制器 1.2.Model:模型 一个功能 一般用JavaBean 1.3.View: ...

  8. Loadrunner 11 中的Java Vuser

    Java vuser是自定义的java虚拟用户脚本,脚本中可以使用标准的java语言. 1.安装jdk 注意,lr11最高支持jdk1.6 2.配置环境变量 3.在lr中选择java vuser协议 ...

  9. Java--面向对象设计

    [转载自本科老师上课课件] 问题一: 在一个软件的功能模块中,需要一种图像处理的功能.该图像处理的策略(如何处理)与图像的内容是相关的.如:卫星的运行图片,使用策略A处理方式,如果是卫星内云图片,则需 ...

  10. python数据类型内置方法

    内容概要 列表内置方法 字典内置方法 字符串转换成字典的方法 eval() 元组内置方法 元组相关笔试题 集合内置方法 列表内置方法 l1 = [2, 4, 5, 7, 3, 9, 0, 6] # 升 ...