题意:给出平面上n个点的坐标,给出起点和终点,找出一条路径使得起点到重点的经过的最长边最短,并输出这个最短的值。
解法:二分长度+bfs判断是否可以到达
//time 112ms
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <set>
#include <queue>
const int maxn = 1005;
using namespace std;
struct Point{
int x,y;
void input(){scanf("%d%d",&x,&y);}
}p[maxn];
struct Edge{
int v,next;
}edge[maxn*maxn];
int n,s,t,en,head[maxn];
int dist[maxn][maxn];
int Dist(Point a,Point b)
{
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
void addedge(int u,int v)
{
edge[en].v = v;
edge[en].next = head[u];
head[u] = en++;
}
void build(int m)
{
en = 0;
memset(head,-1,sizeof(head));
for(int i = 1; i<=n; i++)
for(int j = i+1; j <= n; j++)
if(dist[i][j]<=m)
addedge(i,j),addedge(j,i);
}
bool bfs(int s,int t)
{
queue<int> q;
q.push(s);
bool vis[maxn]={0};
vis[s] = 1;
while(!q.empty())
{
int u = q.front();
q.pop();
for(int i = head[u]; i != -1; i=edge[i].next)
{
int v = edge[i].v;
if(v==t) return 1;
if(!vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
return 0;
}
int main()
{
//freopen("/home/moor/Code/input","r",stdin);
while(scanf("%d",&n)&&n)
{
for(int i = 1; i<=n; i++)
p[i].input();
scanf("%d%d",&s,&t);
int l,r,m,ans;
l = r =0;
for(int i = 1; i<=n; i++)
for(int j = i+1; j <= n; j++)
{
dist[i][j] = dist[j][i] = Dist(p[i],p[j]);
r = max(r,dist[i][j]);
}
while(l<=r)
{
m = (l+r)>>1;
build(m);
if(bfs(s,t)) ans = m,r = m-1;
else l = m+1;
}
printf("%d\n",ans);
}
return 0;
}