题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1815
题意:n个点,每个点可以跟S1或者S2相连,两类约束条件,①a,b不能与同一个S相连 ② a,b必须与同一个相连,问满足条件的每两个点之间的距离的最大值 最小是多少
其中,给出的是每个点坐标,先算距离,距离是曼哈顿距离
分析:二分枚举答案,每次重新建图,边分三类
A表示点a连S1,A’表示点a连S2
① a,b不能与同一个S相连,加边A->B',A'->B,B->A',B'->A;
② a,b必须与同一个S相连,加边A->B,A'->B',B->A,B'->A';
③ a连S1,b连S1距离和大于当前枚举的最大距离 ,加边 A->B',B->A';
a连S2,b连S2距离和大于当前枚举的最大距离 ,加边 A'->B,B'->A;
a连S1,b连S2距离和大于当前枚举的最大距离 ,加边 A->B,B'->A';
a连S2,b连S1距离和大于当前枚举的最大距离 ,加边 A'->B',B->A;
*特别注意一下给的约束条件下标从1开始
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#define maxn 505
#include<cmath>
using namespace std;
int ds1[maxn],ds2[maxn],l;
struct node{
int x,y;
}p[maxn],s1,s2;
int dis(node a,node b){
return abs(a.x-b.x)+abs(a.y-b.y);
}
struct request{
int x,y;
}h[maxn],f[maxn];
struct TwoSAT{
int n;
vector<int> G[maxn*2];
bool mark[maxn*2];
int S[maxn*2],c;
bool dfs(int x){
if(mark[x^1])return false;
if(mark[x])
return true;
mark[x]=true;
S[c++]=x;
for(int i=0;i<G[x].size();i++)
if(!dfs(G[x][i]))
return false;
return true;
}
void init(int n){
this->n=n;
for(int i=0;i<n*2;i++)
G[i].clear();
c=0;
memset(mark,0,sizeof(mark));
}
void add_clause(int x,int xval,int y,int yval){
x=x*2+xval;
y=y*2+yval;
G[x].push_back(y^1);
G[y].push_back(x^1);
}
bool solve(){
for(int i=0;i<n*2;i+=2)
if(!mark[i]&&!mark[i+1]){
c=0;
if(!dfs(i)){
while(c>0)mark[S[--c]]=false;
if(!dfs(i+1))return false;
}
}
return true;
}
};
int main()
{
int n,A,B;
while(~scanf("%d%d%d",&n,&A,&B)){
scanf("%d%d%d%d",&s1.x,&s1.y,&s2.x,&s2.y);
for(int i=0;i<n;i++){
scanf("%d%d",&p[i].x,&p[i].y);
}
for(int i=0;i<A;i++){
scanf("%d%d",&h[i].x,&h[i].y);
}
for(int i=0;i<B;i++){
scanf("%d%d",&f[i].x,&f[i].y);
}
l=dis(s1,s2);
int L =0,R=15000000;
for(int i=0;i<n;i++){
ds1[i]=dis(p[i],s1);
ds2[i]=dis(p[i],s2);
}
TwoSAT T;
int flag=0;
while(L<R){
int m=(L+R)>>1;
T.init(n);
for(int i=0;i<A;i++){
T.add_clause(h[i].x-1,0,h[i].y-1,0);
T.add_clause(h[i].x-1,1,h[i].y-1,1);
}
for(int i=0;i<B;i++){
T.add_clause(f[i].x-1,0,f[i].y-1,1);
T.add_clause(f[i].x-1,1,f[i].y-1,0);
}
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(ds1[i]+ds1[j]>m)
T.add_clause(i,0,j,0);
if(ds2[i]+ds2[j]>m)
T.add_clause(i,1,j,1);
if(ds1[i]+ds2[j]+l>m)
T.add_clause(i,0,j,1);
if(ds2[i]+ds1[j]+l>m)
T.add_clause(i,1,j,0);
}
}
if(T.solve()){
flag=1;
R=m;
}else {
L=m+1;
}
}
if(flag)
printf("%d\n",L);
else
printf("-1\n");
}
return 0;
}