题意:
农场主的牛喜欢串门。。。(又一道奇葩题目。。)
所以农场主得给他的n个牛舍(barn)建造道路,然而农场主觉得花费太多,所以他打算建造两个中转点s1和s2,任意的牛舍要么连s1,要么连s2。
同时还有一些牛舍里的互相讨厌,所以这两个牛舍不能连到同一个中转站。
同时还有一些牛舍里的互相喜欢,所以这两个牛舍要连到同一个中转站。
给你s1和s2的坐标,然后还有n个牛舍的坐标,问你,让牛舍之间的最大距离最短的方案的距离是多少。
距离算的是曼哈顿距离。
思路:
二分距离,每次根据新的距离建边(通过矛盾建立必选关系)。
由于我使用的是链式前向星,所以我保存了cnte和head数组,每次只要在这个基础上建边就好了,不必再动喜欢和讨厌关系建立的边。
撒花完结~2-SAT的7道题都刷穿了23333
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string.h>
#include <queue>
#include <cmath>
#define pi acos(-1.0)
#define eps 1e-6
typedef long long int lli;
using namespace std;
const int maxn = 4200;
struct edge{
int from,to,v,next;
}ed[2000000];
struct node{
int x,y;
}no[600],ha[1200],lo[1200];
node s[2];
int t,a,b;
int head[maxn];int jiluh[maxn];
int cnte,jilu;
void ae(int x,int y){
ed[++cnte].to = y;
ed[cnte].next = head[x];
head[x]=cnte;
}
int dfn[maxn],low[maxn],vis[maxn],stak[maxn],belong[maxn],cntc,cnts,index;//strong connected component //cnt of stack
void dfs(int u){
dfn[u]=low[u] = ++index;
stak[cnts++]=u;
vis[u]=1;
for(int i = head[u];i!=-1;i=ed[i].next){
int v = ed[i].to;
if(!dfn[v]){
dfs(v);
low[u] = min(low[u],low[v]);
}
else if(vis[v]){
low[u] = min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
cntc++;int v;
do{
v = stak[--cnts];
vis[v] = 0;
belong[v] = cntc;
}while(v!=u);
}
}
int n,m;
void tarjan(){
for(int i = 1;i <= 2*n;i++){
if(!dfn[i]){
dfs(i);
}
}
}
double dis(node a,node b){
return ( abs(a.x-b.x) + abs(a.y-b.y) );
}
void ini(){
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(vis,0,sizeof(vis));
memset(belong,0,sizeof(belong));
cntc=index=0;
}
bool jud(){
for(int i = 1;i <= n;i++){
if(belong[i]!=0 &&belong[i] == belong[i+n]){
return false;
}
}
return true;
}
bool build(int mid){
cnte = jilu;
for(int i = 1;i <= 2*n;i++){
head[i] = jiluh[i];
}
for(int i = 1;i <= n;i++){
for(int j = 1;j <= n;j++){
if(i!=j){
if(dis(no[i],s[0])+dis(no[j],s[0]) >mid){
ae(i,j+n);ae(j,i+n);
}
if(dis(no[i],s[1])+dis(no[j],s[1]) >mid){
ae(i+n,j);ae(j+n,i);
}
if(dis(no[i],s[0])+dis(no[j],s[1])+dis(s[0],s[1]) >mid){
ae(i,j);ae(j+n,i+n);
}
if(dis(no[i],s[1])+dis(no[j],s[0])+dis(s[0],s[1])>mid){
ae(i+n,j+n);ae(j,i);
}
}
}
}
ini();tarjan();
if(!jud()){
return false;
}
return true;
}
int main(){
scanf("%d%d%d",&n,&a,&b);
memset(head,-1,sizeof(head));cnte = 0;
scanf("%d%d%d%d",&s[0].x,&s[0].y,&s[1].x,&s[1].y);
for(int i = 1;i <= n;i++){
scanf("%d%d",&no[i].x,&no[i].y);
}
for(int i = 1;i <= a;i++){
scanf("%d%d",&ha[i].x,&ha[i].y);
ae(ha[i].x,ha[i].y+n);ae(ha[i].y,ha[i].x+n);
ae(ha[i].y+n,ha[i].x);ae(ha[i].x+n,ha[i].y);
}
for(int i = 1;i <= b;i++){
scanf("%d%d",&lo[i].x,&lo[i].y);
ae(lo[i].x,lo[i].y);ae(lo[i].x+n,lo[i].y+n);
ae(lo[i].y,lo[i].x);ae(lo[i].y+n,lo[i].x+n);
}
jilu = cnte;
for(int i = 1;i <= 2*n;i++){
jiluh[i] = head[i];
}
tarjan();
if(!jud()){
printf("-1\n");return 0;
}
int mid,l = 1,r = 4000000;
while(l < r){
mid = (l+r)/2;
if(build(mid)){
r = mid;
}
else{
l = mid+1;
}
}
printf("%d\n",r);
}