昨晚改出来了 被墙联通坑死了 手改大数据......
先放题目
Description
故事发生在1486 年的意大利,Ezio 原本只是一个文艺复兴时期的贵族,后来因为家族成员受到圣殿骑士的杀害,决心成为一名刺客。最终,凭借着他的努力和出众的天赋,成为了杰出的刺客大师。刺客组织在他的带领下,为被剥削的平民声张正义,赶跑了原本统治意大利的圣殿骑士首领-教皇亚历山大六世。在他的一生中,经历了无数次惊心动魄、扣人心弦的探险和刺杀。
这次的故事就是他暗杀一位作恶多端的红衣主教。红衣主教可以吸取他周围人的生命力量,而他的红衣教徒也拥有这个力量。红衣主教的家是一个x*y 的长方形房间,也就是说,他的家的四个角坐标分别为(0,0)(x,0)(0,y)(x,y)。教堂的门在(0,0) ,而红衣主教就在 (x,y)的卧室休息。他的家中还有n个守护着他的红衣教徒,站在(ai,bi)。Ezio想要趁主教休息时,从门进入潜入到他的卧室刺杀他,因为主教休息时会脱下红衣,这样吸取生命的力量就消失了。可是守卫他的红衣教徒依然很危险,离红衣教徒太近就会被吸取生命。因此,Ezio想知道,在能刺杀主教的前提,从门到他的卧室的路上,他最远和离他最近的红衣教徒保持多远的距离。注意:教徒都在房间里。
Input
第一行三个整数x,y,n。之后n行,每行两个整数ai,bi ,意义见题目描述。
Output
一行一个数D,表示Ezio能保持的最大距离,保留两位小数。
Sample Input
10 20 2
3 3
6 14
Sample Output
3.00
样例说明
贴着墙走
Data Constraint
数据范围
对 10%的数据n<=10,
对 30%的数据n<=100
对 100%的数据n<=2000
保证输入合法,x,y属于[1,10^6]
这题和去年PION提高的奶酪很像啊虽然当时我是没想出来 先放一波官方题解
我再来解释一波
起点终点断开 则 左边 上面 的墙是连起来的 右边 下面的墙是连起来的 但左上 右下两墙是分开的
我们想办法把这两墙连起来 因为当他连起来以后 起点和终点就分开了 这时这个边集最大值就是最大距离
虽然求最大距离 但我们要从小加边权 为什么呢
当起点终点刚好分开的时候 我们肯定只有一条从一墙到另一墙的路 这时我们选这堆边集里的最大值 用以穿过这个边集
如果我们从大加 万一还有边集 that (定语从句) 最大值比他小的 也可以联通 那就也要穿过这个边集
所以我们从小找答案的话 就不用更新答案了嘛
还有 每个点都要向两个墙连边 而且是取 点 到 每个墙的两个墙 的 最小距离
inline void addedge(int node) {
e[++tot].u = node,e[tot].v = n + 1,e[tot].w = min(s[node].x,y - s[node].y) * 2,e[tot].w *= e[tot].w;
//注意这里取min的是哪两个值 一定要注意啊QvQ
e[++tot].u = node,e[tot].v = n + 2,e[tot].w = min(s[node].y,x - s[node].x) * 2,e[tot].w *= e[tot].w;
}
我这里有点奇怪 因为两点之间距离是 而墙却不用
为了避免 sqrt 的多次运算 我把墙和点的距离就乘起来了...不过还是差不多一样的速度700+ms为什么我们这边的dalao可以跑21ms啊 然后答案要记得除回去
下放很正常的两个代码
//sqrt后置版
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAXN = 2010;
struct human{double x,y;}s[MAXN];
struct edge{double w;int u,v;}e[MAXN * MAXN];
double x,y,ans;
int l[MAXN],n,tot;
inline double min(double i,double j) {return i < j ? i : j;}
inline int f(int p) {return l[p] == p ? p : l[p] = f(l[p]);}
inline short cmp(edge i,edge j) {return i.w < j.w;}
inline void addedge(int node) {
e[++tot].u = node,e[tot].v = n + 1,e[tot].w = min(s[node].x,y - s[node].y) * 2,e[tot].w *= e[tot].w;
e[++tot].u = node,e[tot].v = n + 2,e[tot].w = min(s[node].y,x - s[node].x) * 2,e[tot].w *= e[tot].w;
}
inline double dis(int i,int j) {
double a = abs(s[i].x - s[j].x);
double b = abs(s[i].y - s[j].y);
return a * a + b * b;
}
inline short pd()
{
int a = f(n - 1),b = f(n);
if (a == b) return 0;
return 1;
}
int main()
{
freopen("AC.in","r",stdin);
freopen("AC.out","w",stdout);
scanf("%lf%lf%d",&x,&y,&n);
for (int a = 1 ; a <= n ; ++ a) scanf("%lf%lf",&s[a].x,&s[a].y);
for (int a = 1 ; a <= n ; ++ a) addedge(a);
for (int a = 2 ; a <= n ; ++ a)
for (int b = 1 ; b < a ; ++ b)
e[++tot].u = a,e[tot].v = b,e[tot].w = dis(a,b);
sort(e + 1,e + tot + 1,cmp),n += 2;
for (int a = 1 ; a <= n ; ++ a) l[a] = a;
for (int a = 1,o = 1 ; a <= tot && pd() ; ++ a)
{
int i = f(e[a].u);
int j = f(e[a].v);
if (i == j) continue;
l[j] = i,++o;
ans = max(ans,e[a].w);
}
printf("%.2lf\n",sqrt(ans) / 2);
fclose(stdin);
fclose(stdout);
return 0;
}
//Frocean原版
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAXN = 2010;
struct human{double x,y;}s[MAXN];
struct edge{double w;int u,v;}e[MAXN * MAXN];
double x,y,ans;
int l[MAXN],n,tot;
inline double min(double i,double j) {return i < j ? i : j;}
inline int f(int p) {return l[p] == p ? p : l[p] = f(l[p]);}
inline short cmp(edge i,edge j) {return i.w < j.w;}
inline void addedge(int node) {
e[++tot].u = node,e[tot].v = n + 1,e[tot].w = min(s[node].x,y - s[node].y);
e[++tot].u = node,e[tot].v = n + 2,e[tot].w = min(s[node].y,x - s[node].x);
}
inline double dis(int i,int j) {
double a = abs(s[i].x - s[j].x);
double b = abs(s[i].y - s[j].y);
return sqrt(a * a + b * b) / 2;
}
inline short pd()
{
int a = f(n - 1),b = f(n);
if (a == b) return 0;
return 1;
}
int main()
{
freopen("AC.in","r",stdin);
freopen("AC.out","w",stdout);
scanf("%lf%lf%d",&x,&y,&n);
for (int a = 1 ; a <= n ; ++ a) scanf("%lf%lf",&s[a].x,&s[a].y);
for (int a = 1 ; a <= n ; ++ a) addedge(a);
for (int a = 2 ; a <= n ; ++ a)
for (int b = 1 ; b < a ; ++ b)
e[++tot].u = a,e[tot].v = b,e[tot].w = dis(a,b);
sort(e + 1,e + tot + 1,cmp),n += 2;
for (int a = 1 ; a <= n ; ++ a) l[a] = a;
for (int a = 1,o = 1 ; a <= tot && pd() ; ++ a)
{
int i = f(e[a].u);
int j = f(e[a].v);
if (i == j) continue;
l[j] = i,++o;
ans = max(ans,e[a].w);
}
printf("%.2lf\n",ans);
fclose(stdin);
fclose(stdout);
return 0;
}