POJ 2749 二分 + 2-SAT
題意
傳送門 POJ 2749
題解
最小化最大值問題,二分答案。若任意兩個糧倉間的最大距離不能超過某個值,根據這個限制條件使用 2 − S A T 2-SAT 2−SAT 判斷是否存在合法答案。定義布林變數
x i 為 真 ⇔ 節 點 i 連 接 S 1 x_i 為真 \Leftrightarrow節點i連線S1 xi為真⇔節點i連接S1 對於記恨的兩個節點,有 ¬ ( ( x i ∧ x j ) ∨ ( ¬ x i ∧ ¬ x j ) ) \lnot \big((x_i\land x_j)\lor (\lnot x_i\land\lnot x_j)\big) ¬((xi∧xj)∨(¬xi∧¬xj));對於友好的兩個節點,有 ¬ ( ( x i ∧ ¬ x j ) ∨ ( ¬ x i ∧ x j ) ) \lnot\big((x_i\land \lnot x_j) \lor (\lnot x_i \land x_j)\big) ¬((xi∧¬xj)∨(¬xi∧xj));對於兩個節點 i , j i,j i,j 間的距離,有 i , j i,j i,j 連線 S 1 , S 2 S1,S2 S1,S2 共 2 × 2 2\times 2 2×2 種可能,對於節點間距離大於限制值的情況,記錄約束條件,例如 i , j i,j i,j 都連線 S 1 S1 S1,且 i , j i,j i,j 間的距離大於限制值,則有 ¬ ( x i ∧ x j ) \lnot (x_i \land x_j) ¬(xi∧xj)。
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define maxn 505
#define maxv 1005
#define maxd 12000005
int N, A, B, V, sx[2], sy[2];
int X[maxn], Y[maxn], ht[maxv * 2], fd[maxv * 2], dis[2][maxn], cmp[maxv];
bool used[maxv];
vector<int> G[maxv], rG[maxv], vs;
void dfs(int v)
{
used[v] = 1;
for (int i = 0; i < G[v].size(); i++)
{
int u = G[v][i];
if (!used[u])
dfs(u);
}
vs.push_back(v);
}
void rdfs(int v, int k)
{
used[v] = 1, cmp[v] = k;
for (int i = 0; i < rG[v].size(); i++)
{
int u = rG[v][i];
if (!used[u])
rdfs(u, k);
}
}
int scc()
{
vs.clear();
memset(used, 0, sizeof(used));
for (int v = 0; v < V; v++)
{
if (!used[v])
dfs(v);
}
int k = 1;
memset(cmp, 0, sizeof(cmp));
memset(used, 0, sizeof(used));
for (int i = vs.size() - 1; i >= 0; i--)
{
int v = vs[i];
if (!used[v])
rdfs(v, k++);
}
return k;
}
inline int dist(int x1, int y1, int x2, int y2)
{
return abs(x1 - x2) + abs(y1 - y2);
}
void add_edge(int u, int v)
{
G[u].push_back(v);
rG[v].push_back(u);
}
bool judge(int x)
{
for (int v = 0; v < V; v++)
{
G[v].clear();
rG[v].clear();
}
for (int k = 0; k < A; k++)
{
int i = ht[k], j = ht[A + k];
add_edge(i, N + j);
add_edge(j, N + i);
add_edge(N + i, j);
add_edge(N + j, i);
}
for (int k = 0; k < B; k++)
{
int i = fd[k], j = fd[B + k];
add_edge(i, j);
add_edge(N + j, N + i);
add_edge(N + i, N + j);
add_edge(j, i);
}
int d12 = dist(sx[0], sy[0], sx[1], sy[1]);
for (int i = 0; i < N; i++)
{
for (int j = i + 1; j < N; j++)
{
if (dis[0][i] + dis[0][j] > x)
{
add_edge(i, N + j);
add_edge(j, N + i);
}
if (dis[1][i] + dis[1][j] > x)
{
add_edge(N + i, j);
add_edge(N + j, i);
}
if (dis[0][i] + dis[1][j] + d12 > x)
{
add_edge(i, j);
add_edge(N + j, N + i);
}
if (dis[1][i] + dis[0][j] + d12 > x)
{
add_edge(N + i, N + j);
add_edge(j, i);
}
}
}
scc();
for (int i = 0; i < N; i++)
{
if (cmp[i] && cmp[N + i] && cmp[i] == cmp[N + i])
return 0;
}
return 1;
}
int main()
{
scanf("%d%d%d", &N, &A, &B);
scanf("%d%d%d%d", sx, sy, sx + 1, sy + 1);
for (int i = 0; i < N; i++)
{
scanf("%d%d", X + i, Y + i);
}
for (int i = 0; i < A; i++)
{
scanf("%d%d", ht + i, ht + A + i);
--ht[i], --ht[A + i];
}
for (int i = 0; i < B; i++)
{
scanf("%d%d", fd + i, fd + B + i);
--fd[i], --fd[B + i];
}
for (int i = 0; i <= 1; i++)
{
for (int j = 0; j < N; j++)
{
dis[i][j] = dist(sx[i], sy[i], X[j], Y[j]);
}
}
V = N << 1;
int lb = -1, ub = maxd;
while (ub - lb > 1)
{
int mid = (lb + ub) >> 1;
if (judge(mid))
ub = mid;
else
lb = mid;
}
printf("%d\n", ub == maxd ? -1 : ub);
}
相關文章
- POJ - 3041 Asteroids 【二分圖匹配】AST
- POJ-3061 Subsequence(字首和+二分/尺取)
- POJ1743 Musical Theme(字尾陣列 二分)陣列
- 2-SAT
- POJ 3014:Asteroids(二分匹配,匈牙利演算法)AST演算法
- 淺談2-SAT
- 『筆記』2-SAT筆記
- POJ 3233 Matrix Power Series (矩陣快速冪+等比數列二分求和)矩陣
- POJ 3662 [USACO08JAN]電話線Telephone Lines SPFA+二分答案
- 2-SAT 學習筆記筆記
- D35【模板】2-SAT
- poj 2031
- poj 3461
- 演算法學習筆記:2-SAT演算法筆記
- POJ 1089 Intervals
- POJ 3414 Pots
- poj3417
- POJ 2975 Nim
- poj 3278 BFS
- POJ3259-WormholesWorm
- POJ3414-Pots
- POJ 1442 Black Box
- POJ 2799 IP Networks
- 【BFS】poj 3414 Pots
- Network(POJ-1144)
- POJ 2553 The Bottom of a Graph
- POJ 1861 Network (Kruskal)
- Apple Catching POJ - 2385APP
- P4171 [JSOI2010] 滿漢全席 2-SATJS
- POJ3126-Prime Path
- POJ1426-Find The Multiple
- POJ2251 Dungeon MasterAST
- Dungeon Master(POJ-2251)AST
- POJ 1611 The Suspects 圖論圖論
- POJ 3267 The Cow Lexicon(dp)
- POJ3278 Catch That Cow
- POJ - 3090 Visible Lattice Points
- POJ 2355 Railway Ticket problemAI