这道题目,只要看懂题意,敢于展开,就是一道初中数学好题。
首先设直线为y=kx+b,那么可知答案为Σ(kxi+b-yi)/(k^2+1),展开以后维护若干个东西就可以化简为(Ab^2+(Xk+Y)b+Uk^2+Vk+W)/(k^+1)的形式,其中A>0,那么以b为主元,最小值为(4ac-b^2)/4a,化简一下可以变成Ak^2+Bk+C/(k^2+1)的形式(A,B,C不同于之前的A,B,C),然后有两种做法,一种是变成A+(B'k+C')/(k^2+1)的形式然后双勾函数;或者设答案为t,以k为主元△>=0,然后可得到答案是一个范围,输出下界即可。
窝用的是△法。
于是只要各种姿势维护需要的关于xi,yi的一些和记好了。AC代码如下:
#include<bits/stdc++.h>
#define N 100005
using namespace std;
int n,m,cnt,tot,q[N],fst[N],pnt[N<<1],nxt[N<<1],fa[N],d[N],sz[N],son[N],anc[N],id[N],rt[N];
int tx[N],ty[N]; bool vis[N];
struct node{
int p[6];
void ins(int u,int v){
p[0]++; p[1]+=u; p[2]+=u*u;
p[3]+=v; p[4]+=v*v; p[5]+=u*v;
}
double calc(){
double A=p[2]-1.*p[1]*p[1]/p[0];
double B=2*p[5]-2.*p[1]*p[3]/p[0];
double C=p[4]-1.*p[3]*p[3]/p[0];
double a=4,b=-4*(A+C),c=4*A*C-B*B;
return (-b-sqrt(b*b-4*a*c))/a/2;
}
}a[N],b[N];
node operator +(node x,node y){
int i; for (i=0; i<6; i++) x.p[i]+=y.p[i]; return x;
}
node operator -(node x,node y){
int i; for (i=0; i<6; i++) x.p[i]-=y.p[i]; return x;
}
void add(int x,int y){
pnt[++tot]=y; nxt[tot]=fst[x]; fst[x]=tot;
}
void dfs(int x,int z){
int i,y; vis[x]=1; sz[x]=1; son[x]=0; rt[x]=z;
a[x]=a[fa[x]]; a[x].ins(tx[x],ty[x]);
for (i=fst[x]; i; i=nxt[i]){
y=pnt[i];
if (!vis[y] && y!=fa[x]){
d[y]=d[x]+1; fa[y]=x;
dfs(y,z); sz[x]+=sz[y];
if (sz[y]>sz[son[x]]) son[x]=y;
}
}
}
void dvd(int x,int tp){
int i,y; anc[x]=tp;
if (son[x]) dvd(son[x],tp);
for (i=fst[x]; i; i=nxt[i]){
y=pnt[i];
if (x==fa[y] && y!=son[x]) dvd(y,y);
}
}
int lca(int x,int y){
for (; anc[x]!=anc[y]; x=fa[anc[x]])
if (d[anc[x]]<d[anc[y]]) swap(x,y);
return (d[x]<d[y])?x:y;
}
void cir(){
int i,x,y; memset(vis,0,sizeof(vis));
for (x=1; x<=n; x++)
for (i=fst[x]; i; i=nxt[i]) if (fa[x]!=pnt[i] && fa[pnt[i]]!=x){
y=pnt[i];
if (d[x]>d[y]) swap(x,y);
for (; y!=x; y=fa[y]){
q[++cnt]=y; id[y]=cnt; vis[y]=1;
b[cnt]=b[cnt-1]; b[cnt].ins(tx[y],ty[y]);
}
q[++cnt]=x; id[x]=cnt; vis[x]=1;
b[cnt]=b[cnt-1]; b[cnt].ins(tx[x],ty[x]);
return;
}
}
int main(){
scanf("%d%d",&n,&m);
int i,x,y;
for (i=1; i<=n; i++) scanf("%d%d",&tx[i],&ty[i]);
for (i=1; i<=m; i++){
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
dfs(1,1);
memset(vis,0,sizeof(vis));
if (n==m) cir(); else q[cnt=1]=1;
memset(fa,0,sizeof(fa));
for (i=1; i<=cnt; i++){
dfs(q[i],q[i]); dvd(q[i],q[i]);
}
scanf("%d",&m);
node u,v;
while (m--){
scanf("%d%d",&x,&y);
if (rt[x]==rt[y]){
u=a[x]+a[y]-a[lca(x,y)]-a[fa[lca(x,y)]];
printf("%.5f\n",u.calc());
} else{
if (id[rt[x]]>id[rt[y]]) swap(x,y);
u=a[x]-a[rt[x]]+a[y]-a[rt[y]]+b[id[rt[y]]]-b[id[rt[x]]-1];
v=a[x]-a[rt[x]]+a[y]-a[rt[y]]+b[id[rt[x]]]+b[cnt]-b[id[rt[y]]-1];
printf("%.5f\n",min(u.calc(),v.calc()));
}
}
return 0;
}
by lych
2017.3.15