您的位置:首页 > 产品设计 > UI/UE

POJ 2749 - Building roads(2-SAT+二分)

2015-04-06 10:12 295 查看
题目:

http://poj.org/problem?id=2749

题意:

有n个牛棚, 有两个特殊点P1, P2,牛棚只能连接P1, P2, 有A个牛棚不能连在同一个点,有B个牛棚一定要连在同一个点,求出最小的最长距离,(距离是曼哈顿距离.

思路:

2-SAT + 二分.

每次二分后重新建边,互为敌人,互为朋友,以及距离超过mid的两点不能建边.

关键是边的相连.想把或表达式列出.

x hate y: x&y = 0, !x&!y = 0 : !x ^ !y = 1, x^y = 1 : <x,!y>,<y, !x>, <!x, y>, <!y, x>

x frend y : x&!y=0, !x&y=0 : !x^y=1, x^!y=1: <x,y>, <!x,!y>, <y,x>,<!y,!x>.

两点之间距离大于mid也要有限制,具体看代码.

AC.

#include <iostream>
#include <cstdio>
#include <stack>
#include <vector>
#include <cstring>
#include <cmath>

using namespace std;
const int MAXN = 1005;
const int MAXM = MAXN*MAXN*2;
int N, H, F;
int D;
struct node {
int x, y;
};
node P1, P2, barn[MAXN], hate[MAXN], frd[MAXN];

int n, m;
struct edge {
int to, next;
}edge[MAXM];
int head[MAXN], tot;

void init()
{
tot = 0;
memset(head, -1, sizeof(head));
}

void addedge(int u, int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}

int low[MAXN], dfn[MAXN], belong[MAXN];
int scc, Index;
stack<int> S;

void tarjan(int u)
{
int v;
low[u] = dfn[u] = ++Index;
S.push(u);
for(int i = head[u]; i != -1; i = edge[i].next) {
v = edge[i].to;
if(!dfn[v]) {
tarjan(v);
if(low[u] > low[v]) low[u] = low[v];
}
else if(!belong[v] && low[u] > dfn[v]) {
low[u] = dfn[v];
}
}
if(low[u] == dfn[u]) {
scc++;
do {
v = S.top(); S.pop();
belong[v] = scc;
}while(v != u);
}
}
int dis(node P, node Bn)
{
return abs(P.x-Bn.x) + abs(P.y-Bn.y);
}

void build(int mid)
{
init();
int u, v;
for(int i = 0; i < H; ++i) {
u = hate[i].x; v = hate[i].y;
addedge(u, N+v);
addedge(v, N+u);
addedge(N+u, v);
addedge(N+v, u);
}
for(int i = 0; i < F; ++i) {
u = frd[i].x; v = frd[i].y;
addedge(u, v);
addedge(v, u);
addedge(N+v, N+u);
addedge(N+u, N+v);
}

for(int i = 0; i < N; ++i) {
for(int j = i+1; j < N; ++j) {
if(dis(barn[i], P1)+dis(P1, barn[j]) > mid) {
addedge(i, N+j);
addedge(j, N+i);
}
if(dis(barn[i], P2)+dis(barn[j],P2) > mid) {
addedge(N+i, j);
addedge(N+j, i);
}
if(dis(barn[i], P1)+D+dis(barn[j], P2) > mid) {
addedge(i, j);
addedge(N+j, N+i);
}
if(dis(barn[i], P2)+D+dis(barn[j], P1) > mid) {
addedge(N+i, N+j);
addedge(j, i);
}
}
}
}
bool solve(int mid)
{
//printf("%d\n", mid);
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
memset(belong, 0, sizeof(belong));

build(mid);

Index = scc = 0;
for(int i = 0; i < 2*N; ++i) {
if(!dfn[i]) tarjan(i);
}

for(int i = 0; i < N; ++i) {
if(belong[i] == belong[N+i]) {
return false;
}
}
return true;
}

int main()
{
//freopen("in", "r", stdin);

while(~scanf("%d %d %d", &N, &H, &F)) {

scanf("%d %d %d %d", &P1.x, &P1.y, &P2.x, &P2.y);
D = dis(P1, P2);

for(int i = 0; i < N; ++i) {
scanf("%d %d", &barn[i].x, &barn[i].y);
}
for(int i = 0; i < H; ++i) {
scanf("%d %d", &hate[i].x, &hate[i].y);
hate[i].x--; hate[i].y--;
}
for(int i = 0; i < F; ++i) {
scanf("%d %d", &frd[i].x, &frd[i].y);
frd[i].x--; frd[i].y--;
}

int l = 0, r = 4e6;
while(r-l > 1) {
int mid = (l+r)/2;

if(solve(mid)) r = mid;
else l = mid;
}
if(r == 4e6) printf("-1\n");
else {
if(solve(l)) r = l;
printf("%d\n", r);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  POJ