标签:
题目大意:给出N个农场,S1场地和S2场地的坐标,要求每个农场要么和S1场地连接要么和S2场地连接,且每个农场之间的连接距离的最大值最小
现在给出A种不可连接限制,表明两个农场不能和同一个场地连接
又给出B种连接限制,表明两个农场要和同一个场地连接
解题思路:这题处理时有点恶心
二分枚举最大距离L,判断一下每个农场可连接的场地(以下的连边表示,a表示和S1连接,!a表示和S2连接)
如果dist(a,S1) > L,那么a农场只能和S2连接了,连边a -> !a (a->!a表示只要dfs到a,那么必然返回false,说明a农场只能和S2相连)
如果dist(a,S2) > L,那么a农场只能和S1连接了,连边!a ->a
如果dist(a, S1) + dist(b,S1) > L,那么表明a和b不能同时和S1连接,连边a -> !b, b->!a
如果dist(a, S2) + dist(b,S2) > L,那么表明a和b不能同时和S2连接,连边!a -> b, !b->a
如果dist(a,S1) + dist(b, S2) + dist(S1,S2) > L,那么表明a农场连接S1时,b农场不能连接S2。b农场连接S2时,a农场不能连接S1,连边 a->b, !b->!a
如果dist(a,S2) + dist(b, S1) + dist(S1,S2) > L,那么表明a农场连接S2时,b农场不能连接S1。b农场连接S1时,a农场不能连接S2,连边 !a->!b, b->a
接下来还要处理A中不可连接限制和B种连接限制,这些就不提了,能处理上面的,下面的可定也能处理
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define N 1010
#define abs(a) ((a) > 0? (a): (-(a)))
struct cows{
int x, y;
}C[N], S1, S2, heat[N], like[N];
int n, m, a, b, top, dis_S1_S2;
int S[N], dis_S1[N], dis_S2[N];
bool mark[N];
vector<int> G[N];
void init() {
scanf("%d%d%d%d", &S1.x, &S1.y, &S2.x, &S2.y);
dis_S1_S2 = abs(S1.x - S2.x) + abs(S1.y - S2.y);
for (int i = 0; i < m; i++) {
scanf("%d%d", &C[i].x, &C[i].y);
dis_S1[i] = abs(C[i].x - S1.x) + abs(C[i].y - S1.y);
dis_S2[i] = abs(C[i].x - S2.x) + abs(C[i].y - S2.y);
}
for (int i = 0; i < a; i++) {
scanf("%d%d", &heat[i].x, &heat[i].y);
heat[i].x--; heat[i].y--;
}
for (int i = 0; i < b; i++) {
scanf("%d%d", &like[i].x, &like[i].y);
like[i].x--; like[i].y--;
}
}
bool dfs(int u) {
if (mark[u ^ 1]) return false;
if (mark[u]) return true;
mark[u] = true;
S[++top] = u;
for (int i = 0; i < G[u].size(); i++)
if (!dfs(G[u][i]))
return false;
return true;
}
void AddEdge(int x, int valx, int y, int valy) {
x = 2 * x + valx;
y = 2 * y + valy;
G[x].push_back(y);
}
bool judge(int mid) {
for (int i = 0; i < 2 * m; i++)
G[i].clear();
bool flag;
for (int i = 0; i < m; i++) {
flag = false;
//不能和S1相连
if (dis_S1[i] > mid) {
AddEdge(i, 0, i, 1);
flag = true;
}
//不能和S2相连
if (dis_S2[i] > mid) {
if (flag)
return false;
AddEdge(i, 1, i, 0);
}
}
for (int i = 0; i < m; i++)
for (int j = i + 1; j < m; j++) {
//第i个和第j个能够和S1相连的情况
if (dis_S1[i] <= mid && dis_S1[j] <= mid && dis_S1[i] + dis_S1[j] > mid) {
AddEdge(i, 0, j, 1);
AddEdge(j, 0, i, 1);
}
//第i个和第j个能够和S2相连的情况
if (dis_S2[i] <= mid && dis_S2[j] <= mid && dis_S2[i] + dis_S2[j] > mid) {
AddEdge(i, 1, j, 0);
AddEdge(j, 1, i, 0);
}
//第i个和S1相连,第j个和S2相连
if (dis_S1[i] <= mid && dis_S2[j] <= mid && dis_S1[i] + dis_S2[j] + dis_S1_S2 > mid) {
AddEdge(i, 0, j, 0);
AddEdge(j, 1, i, 1);
}
//第i个和S2相连,第j个和s1相连
if (dis_S2[i] <= mid && dis_S1[j] <= mid && dis_S2[i] + dis_S1[j] + dis_S1_S2 > mid) {
AddEdge(i, 1, j, 1);
AddEdge(j, 0, i, 0);
}
}
for (int i = 0; i < a; i++) {
AddEdge(heat[i].x, 0, heat[i].y, 1);
AddEdge(heat[i].x, 1, heat[i].y, 0);
AddEdge(heat[i].y, 0, heat[i].x, 1);
AddEdge(heat[i].y, 1, heat[i].x, 0);
}
for (int i = 0; i < b; i++) {
AddEdge(like[i].x, 0, like[i].y, 0);
AddEdge(like[i].x, 1, like[i].y, 1);
AddEdge(like[i].y, 0, like[i].x, 0);
AddEdge(like[i].y, 1, like[i].x, 1);
}
memset(mark, 0, sizeof(mark));
for (int i = 0; i < 2 * m; i++) {
if (!mark[i] && !mark[i ^ 1]) {
top = 0;
if (!dfs(i)) {
while (top) mark[S[top--]] = false;
if (!dfs(i ^ 1))
return false;
}
}
}
return true;
}
void solve() {
int l = 0, r = 44444444, mid;
int ans = -1;
while (l <= r) {
mid = (l + r) / 2;
if (judge(mid)) {
ans = mid;
r = mid - 1;
}
else
l = mid + 1;
}
printf("%d\n", ans);
}
int main() {
while (scanf("%d%d%d", &m, &a, &b) != EOF) {
init();
solve();
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU - 1815 Building roads (2-SAT)
标签:
原文地址:http://blog.csdn.net/l123012013048/article/details/47417833