题目:
https://ac.nowcoder.com/acm/problem/21315
平面上有
N
N
N个城市和
M
M
M个乡村,一开始没有任何的道路
为了改善这个局面,主席决定采取一些策略使得每个乡村都能连接到至少一个城市
当存在一个乡村与任何城市都没有联系时,执行如下操作
- 随机挑选一个未联系的乡村 V V\quad V
- 选择离 V V V最近(欧几里得距离)的一个已链接城市的乡村或者城市,如果有多个,满足条件的点,随机选择,假设选择的点为 P P P
- 在
V
V
V与
P
P
P之间 建设一条道路
求期望需要修建多长的道路能使得所有的乡村都能直接或者间接的连接到城市
思路:
可以发现,对于每一个挑选的乡村
V
V
V,进行连边操作后,一定能够使
V
V
V直接或间接连到城市(即一个乡村只会操作一次)。令
X
i
X_i
Xi为第
i
i
i个乡村连出去的边的长度的随机变量,
X
X
X为整个图的长度的随机变量,有
E
(
X
)
=
∑
i
=
1
N
E
(
X
i
)
E(X)=\sum_{i=1}^{N}E(X_i)
E(X)=i=1∑NE(Xi)
对于每一个乡村来说,要么连乡村要么连城市,令
P
(
x
,
y
)
P(x,y)
P(x,y)表示从
x
x
x连向
y
y
y的概率,
c
i
c_i
ci表示城市,
v
i
v_i
vi表示乡村,则
E
(
X
i
)
=
∑
j
=
1
N
P
(
v
i
,
v
j
)
d
i
s
(
v
i
,
v
j
)
+
∑
j
=
1
M
P
(
v
i
,
c
j
)
d
i
s
(
v
i
,
c
j
)
E(X_i)=\sum_{j=1}^{N}P(v_i,v_j)dis(v_i,v_j)+\sum_{j=1}^{M}P(v_i,c_j)dis(v_i,c_j)
E(Xi)=j=1∑NP(vi,vj)dis(vi,vj)+j=1∑MP(vi,cj)dis(vi,cj)
我们先来考虑连向城市,会发现只需要考虑离
v
i
v_i
vi最近的城市即可,记为
c
j
c_j
cj,假设还有
x
x
x个乡村比
c
j
c_j
cj离得更近,则操作
1
1
1的顺序必须满足
v
i
v_i
vi排在这
x
x
x个乡村之前(相对位置),则
P
(
v
i
,
c
j
)
=
1
x
+
1
P(v_i,c_j)=\frac{1}{x+1}
P(vi,cj)=x+11
同理对于在这
x
x
x个乡村中是第
y
y
y近的乡村
v
j
v_j
vj来说,有
P
(
v
i
,
v
j
)
=
1
y
(
y
+
1
)
P(v_i,v_j)=\frac{1}{y(y+1)}
P(vi,vj)=y(y+1)1
貌似不用考虑存在相同的距离
#include <cmath>
#include <iostream>
#include <iomanip>
#include <algorithm>
using namespace std;
const int maxn = 55;
const double eps = 1e-9;
struct point {
int x, y;
bool isc;
} c[maxn], v[maxn], t[maxn << 1];
inline double sqr(double x) { return x * x; }
inline double dis(const point& a, const point& b) {
return sqrt(1.0 * sqr(a.x - b.x) + sqr(a.y - b.y));
}
int i, j;
bool cmp (const point& a, const point& b) {
return dis(v[i], a) == dis(v[i], b) ? a.isc < b.isc : dis(v[i], a) < dis(v[i], b);
}
int main() {
int n, m;
cin >> n >> m;
for (i = 0; i < n; i++)
cin >> c[i].x;
for (i = 0; i < n; i++)
cin >> c[i].y;
for (i = 0; i < m; i++)
cin >> v[i].x;
for (i = 0; i < m; i++)
cin >> v[i].y;
double ans = 0;
for(i = 0; i < m; i++) {
int cnt = 0;
for (j = 0; j < n; j++)
t[cnt] = c[j], t[cnt++].isc = 1;
for (j = 0; j < m; j++) if(i != j)
t[cnt] = v[j], t[cnt++].isc = 0;
sort(t, t + cnt, cmp);
for (j = 0; j < cnt; j++) {
if(t[j].isc == 1) {
ans += dis(t[j], v[i]) / (j + 1);
break;
}
ans += dis(t[j], v[i]) / (j + 1) / (j + 2);
}
}
cout << fixed << setprecision(10) << ans << endl;
return 0;
}