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

poj2749 Building roads

2017-01-29 20:51 246 查看
Building roads
题目背景:
poj2749
分析:本题的建边比较繁琐,并且需要二分答案来寻找最小的曼哈顿距离然后2-SAT求解,因此,每一次二分一个上界,然后根据上界limit, 然后根据喜欢讨厌关系和如下关系建边tarjan即可。如还不太清楚2-SAT,可以去看这篇
dist(i, S1) + dist(S1, j) > limit  ó Xi->!Xj  Xj->Xi
dist(i, S2) + dist(S2, j) > limit  ó !Xi->Xj  !Xj->Xi
dist(i, S1) + dist(S1, S2) + dist(S2, j) > limit
ó !Xj->!Xi Xi->Xj

dist(i, S2) + dist(S2, S1) + dist(S1, j) > limit
ó !Xi->!Xj Xj->Xi
 
Source:
#include
#include
#include
#include
#include
#include
#include
#include

using namespace std;

inline void R(int &v)
{
char c = 0;
bool p = true;
v = 0;
while(!isdigit(c))
{
if(c == '-')
p = false;
c = getchar();
}
while(isdigit(c))
{
v = (v << 3) + (v << 1) + (c ^ '0');
c = getchar();
}
if(!p)
v = -v;
}

const int MAXN = 50000 + 10;
const int MAXM = 1000000;

stack  s;
int dist[MAXN << 1][2], dis12, tot, first[MAXN << 1], n, a, b;
int num[MAXN << 1], low[MAXN << 1], ind, cnt, scc[MAXN << 1];
struct P { int x, y; } point[MAXN], s1, s2;
struct node { int next, to; } edge[MAXM];
int like[1010][2], hate[1010][2];
bool exist[MAXN << 1];

inline int dis(int i, int j) { return abs(point[j].y - point[i].y) + abs(point[j].x - point[i].x); }

inline void create(int x, int y) { tot++, edge[tot].next = first[x], first[x] = tot, edge[tot].to = y; }

void read()
{
R(n), R(a), R(b), R(s1.x), R(s1.y), R(s2.x), R(s2.y);
point[0] = s1, point[n + 1] = s2;
for(int i = 1; i <= n; ++i) R(point[i].x), R(point[i].y);
for(int i = 1; i <= a; ++i) R(hate[i][0]), R(hate[i][1]);
for(int i = 1; i <= b; ++i) R(like[i][0]), R(like[i][1]);
}

void pre()
{
dis12 = dis(0, n + 1);
for(int i = 1; i <= n; ++i)
{
dist[i][0] = dis(0, i);
dist[i][1] = dis(n + 1, i);
}
}

void build(int x)
{
for(int i = 1; i <= a; ++i) create(hate[i][0], hate[i][1] + n), create(hate[i][0] + n, hate[i][1]), create(hate[i][1], hate[i][0] + n), create(hate[i][1] + n, hate[i][0]);
for(int i = 1; i <= b; ++i) create(like[i][0], like[i][1]), create(like[i][1], like[i][0]), create(like[i][0] + n, like[i][1] + n), create(like[i][1] + n, like[i][0] + n);
for(int i = 1; i <= n; ++i)
for(int j = i + 1; j <= n; ++j)
{
if(dist[i][0] + dist[j][0] > x) create(i, j + n), create(j, i + n);
if(dist[i][1] + dist[j][1] > x) create(i + n, j), create(j + n, i);
if(dist[i][0] + dis12 + dist[j][1] > x) create(i, j), create(j + n, i + n);
if(dist[i][1] + dis12 + dist[j][0] > x) create(i + n, j + n), create(j, i);
}
}

void dfs(int cur)
{
num[cur] = low[cur] = ++ind;
exist[cur] = true;
s.push(cur);
for(int p = first[cur]; p; p = edge[p].next)
{
if(!num[edge[p].to]) dfs(edge[p].to), low[cur] = min(low[cur], low[edge[p].to]);
else if(exist[edge[p].to]) low[cur] = min(low[cur], num[edge[p].to]);
}
if(num[cur] == low[cur])
{
int o = s.top();
cnt++;
while(o != cur) exist[o] = false, s.pop(), scc[o] = cnt, o = s.top();
exist[o] = false, s.pop(), scc[o] = cnt;
}
}

void clear()
{
tot = cnt = ind = 0;
memset(first, 0, sizeof(first));
memset(num, 0, sizeof(num));
memset(exist, 0, sizeof(exist));
while(!s.empty()) s.pop();

}

bool check(int x)
{
clear();
build(x);
for(int i = 1; i <= (n << 1); ++i)
if(!num[i]) dfs(i);
for(int i = 1; i <= n; ++i)
if(scc[i] == scc[i + n]) return false;
return true;
}

void work()
{
const int MAXX = 30000000;
int l = -1, r = MAXX;
while(l + 1 < r)
{
register int mid = l + r >> 1;
if(check(mid))
r = mid;
else
l = mid;
}
cout << (r == MAXX ? -1 : r) ;
}

int main()
{
read();
pre();
work();
return 0;
}



 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: