#include<iostream>
#include<vector>
#include<cmath>
#include<cstdlib>
#define N 1003
#include<cstring>
#include<cstdio>
using namespace std;
int n_barn, n_hate, n_friend; int len;
int stack[2*N]; int low[2*N]; int dfn[2*N]; bool in_stack[2*N]; int scc[2*N];
int color,index,top;
int done;
int n;
struct Point
{
int x,y;
};
Point cor1,cor2;
int dist[2*N];
vector <int> gt[2*N];
vector<int> g[2*N];
void init(int max_dist);
void tarjan(int s);
int get_dist(Point &p,Point &q);
void solve();
int b_search();
int check();
int main()
{
freopen("in.txt","r",stdin);
int x,y;
Point point;
while(cin>>n_barn>>n_hate>>n_friend){
cin>>cor1.x>>cor1.y>>cor2.x>>cor2.y;
len=get_dist(cor1,cor2);
n=2*n_barn;
for(int i=0;i<2*N;i++) gt[i].clear();
for(int i=0;i<n_barn;i++)
{
scanf("%d%d",&point.x,&point.y);
dist[2*i]=get_dist(point,cor1);
dist[2*i+1]=get_dist(point,cor2);
}
for(int i=0;i<n_hate;i++)
{
scanf("%d%d",&x,&y);
x-=1; y-=1;
gt[2*x].push_back(2*y+1);
gt[2*x+1].push_back(2*y);
gt[2*y].push_back(2*x+1);
gt[2*y+1].push_back(2*x);
}
for(int i=0;i<n_friend;i++)
{
scanf("%d%d",&x,&y);
x-=1; y-=1;
gt[2*x].push_back(2*y);
gt[2*y].push_back(2*x);
gt[2*x+1].push_back(2*y+1);
gt[2*y+1].push_back(2*x+1);
}
x=b_search();
if(done)
cout<<x<<endl;
else cout<<-1<<endl;
}
}
void init(int max_dist)
{
for(int i=0;i<n;i++)
g[i]=gt[i];
for(int i=0;i<n_barn;i++)
for(int j=i+1;j<n_barn;j++)
{
if(dist[2*i]+dist[2*j]>max_dist)
{
g[2*i].push_back(2*j+1);
g[2*j].push_back(2*i+1);
}
if(dist[2*i]+dist[2*j+1]+len>max_dist)
{
g[2*i].push_back(2*j);
g[2*j+1].push_back(2*i+1);
}
if(dist[2*i+1]+dist[2*j]+len>max_dist)
{
g[2*i+1].push_back(2*j+1);
g[2*j].push_back(2*i);
}
if(dist[2*i+1]+dist[2*j+1]>max_dist)
{
g[2*i+1].push_back(2*j);
g[2*j+1].push_back(2*i);
}
}
}
void tarjan(int s)
{
low[s]=dfn[s]=++index;
stack[top++]=s;
in_stack[s]=true;
vector <int> :: iterator p;
for(p=g[s].begin();p!=g[s].end();p++)
{
if(!dfn[*p])
{tarjan(*p);
low[s]=min(low[s],low[*p]);
}
else if(in_stack[*p]) // 必须是在栈内
{
low[s]=min(low[s],dfn[*p]);
}
}
if(dfn[s]==low[s])
{
color++;
int t;
do{
t=stack[top-1];
scc[t]=color;
top--;
in_stack[t]=false;
}while(t!=s);
}
}
void solve()
{
memset(in_stack,0,sizeof(in_stack));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
index=0; top=0; color=0;
for(int i=0;i<2*n;i++)
if(!dfn[i])
tarjan(i);
}
int check()
{
for(int i=0;i<2*n;i+=2)
{
if(scc[i]==scc[i+1])
return 0;
}
return 1;
}
int get_dist(Point &p,Point &q)
{
return abs(p.x-q.x)+abs(p.y-q.y);
}
int b_search()
{
done=0;
int l=0;int r=5000000;
int mid;
while(l<r)
{
mid=(l+r)/2;
init(mid);
solve();
if(!check())
l=mid+1;
else {r=mid; done=1;}
}
return l;
}
开始题意理解错了 以为求路径总和最短,
题目描述: 有n个牛棚,两个中转点M1,M2,牛棚只能连到中转点,
而且有些牛棚只能连到相同的中转点,有些牛棚只能连在 不同的中转点;
要求最后使得牛棚之间最长距离 最小。
关于最大最小之类的,都是二分答案 多学习···
对于x y讨厌的关系:加边x->~y, y->~x, ~x -> y, ~y->x
对于x y喜欢的关系:加边x ->y, y->x ~x->~y, ~y->~x
另外,对于二分的最长路 mid: 如果直接相连的两点 d[i]+d[j] > mid,
表示必须连到不同中转点,加边i->~j, j->~i
如果两点连到不同中转点d[i]+d[j]+D>mid, 表示必须连到相同点,加边i->j, j->i