题意:有一条线段,和n个点,把n个点连接在线段的端点处。。有a对点要连接在同一个点上,有b对点要连接在不同的点上。要使任意两点的最长距离最短。求最短距离
思路:假设有2*n个点,i点表示连接在start端,i+n表示连接在end端,则连接同一点的点对 i , j 有:i->j j->i i+n->j+n j+n->i+n
连在不同一点的点对:i,j 有: i->j+n j->i+n j+n->i i+n->j
距离的限制在注释里有。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
const int N = 2009;
const int M = 2009;
const int INF = 0x3f3f3f3f;
int n,a,b;
struct cpoint{
int x,y;
void get(){scanf("%d%d",&x,&y);}
}star,end,re[N];
struct edge{
int l,r;
void get(){scanf("%d%d",&l,&r);}
} e1[M],e2[M];
int dist(cpoint &a,cpoint &b){
//cout<<((a.x>b.x?a.x-b.x:b.x-a.x)+(a.y>b.y?a.y-b.y:b.y-a.y))<<endl;
return (a.x>b.x?a.x-b.x:b.x-a.x)+(a.y>b.y?a.y-b.y:b.y-a.y);
}
stack<int> S;
bool post[N];
int dfn[N],low[N],col[N],color,ind;
struct LT{
int to,nex;
} L[1000009];
int F[N],cnt;
void add(int f,int t)
{
//cout<<f<<" "<<t<<endl;
L[cnt].nex = F[f];
L[cnt].to = t;
F[f] = cnt++;
}
void tdfs(int k,int fa)
{
//cout<<k<<" "<<fa<<endl;
dfn[k] = low[k]=ind++;
post[k]=1;S.push(k);
for(int i=F[k];i;i=L[i].nex)
{
int to = L[i].to;
// if(to==fa) continue;
if(!dfn[to])
{
tdfs(to,k);
low[k] = min(low[to],low[k]);
}
else if(post[to]&&dfn[to]<low[k])
{
low[k] =dfn[to];
}
}
if(low[k]==dfn[k])
{
int i;color++;
for(i=S.top(),S.pop();i!=k;i=S.top(),S.pop())
{
post[i]=0;col[i] = color;
}
post[k]=0,col[k]=color;
}
}
bool tarjan()
{
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(col,0,sizeof(col));
ind = 1,color=0;
for(int i=1;i<=(n<<1);i++)
if(!dfn[i]) tdfs(i,-1);
for(int i=1;i<=n;i++)
if(col[i]==col[i+n]) return false;
return true;
}
int main()
{
freopen("in.txt","r",stdin);
scanf("%d%d%d",&n,&a,&b);
star.get();end.get();
for(int i=1;i<=n;i++) re[i].get();
for(int i=1;i<=a;i++) e1[i].get();
for(int i=1;i<=b;i++) e2[i].get();
int ans = INF;
int l=0,r=INF,mid;
//cout<<INF<<endl;
while(l<=r)
{
mid=(l+r)>>1;
memset(F,0,sizeof(F));cnt=1;
for(int i=1;i<=a;i++)
add(e1[i].l,e1[i].r+n),add(e1[i].l+n,e1[i].r),
add(e1[i].r,e1[i].l+n),add(e1[i].r+n,e1[i].l);
for(int i=1;i<=b;i++)
add(e2[i].l,e2[i].r),add(e2[i].l+n,e2[i].r+n),
add(e2[i].r,e2[i].l),add(e2[i].r+n,e2[i].l+n);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
{
if(dist(re[i],star)+dist(re[j],star)>mid)
add(i,j+n),add(j,i+n);/// i在star 则 j不能在star,同理。。
if(dist(re[i],end)+dist(re[j],end)>mid)
add(i+n,j),add(j+n,i);/// i在end 则 j不能在end,同理。。
if(dist(re[i],star)+dist(end,re[j])>mid-dist(star,end))
add(i,j),add(j+n,i+n);/// i在star 则 j不能在end ,同理。。
if(dist(re[i],end)+dist(star,re[j])>mid-dist(star,end))
add(i+n,j+n),add(j,i);/// i在end 则 j不能在star ,同理。。
}
if(!tarjan())
l=mid+1;//,cout<<l<<" "<<r<<endl;
else ans=mid,r=mid-1;
}
printf("%d\n",ans==INF?-1:ans);
return 0;
}