题目:C. Rencontre
大致题意:有n个旅馆,有3个集合分别包含了各自的旅馆。
在每个集合中选择一个旅馆之后确定了3个旅馆的位置,再选择一个旅馆v,使得三个旅馆到v旅馆的总距离最小,问路线的期望总长度。
画图可以发现,树上的三个点找到一个点使之距离最小,必是三个点中的一个,将其中一个视作中点,但是确定三个点之后,还得计算是哪一个最小的,由于有一个是中点,可以直接相加三个点的互相距离最后除以2。
证明
比
较
x
+
y
+
z
和
2
m
i
n
的
大
小
比较x+y+z和2min的大小
比较x+y+z和2min的大小,两端乘以一个2,利用不等式
x
+
y
>
m
i
n
x+y>min
x+y>min即可证明。
E
(
x
)
=
∑
∑
∑
1
2
∗
(
d
i
s
(
1
,
2
)
+
d
i
s
(
2
,
3
)
+
d
i
s
(
1
,
3
)
)
∗
p
E(x)=\sum\sum\sum\frac{1}{2}*(dis(1,2)+dis(2,3)+dis(1,3))*p
E(x)=∑∑∑21∗(dis(1,2)+dis(2,3)+dis(1,3))∗p
由于n范围大还得继续化简,可以从边入手,分开成两个集合,判断分割的数量,例如({1},{2,3})以此。分情况讨论。
#include<bits/stdc++.h>
#define mmp make_pair
#define inf 0x3f3f3f3f
#define llinf 0x7fffffffffffffff
using namespace std;
typedef long long ll;
typedef pair<int,int> PP;
typedef double ld;
const ll mod=1e9+7;
const int maxn=3e6+10;
vector<PP>hh[200010];
set<int>gym[5];
int dp[200010][4];
void dfs(int u,int f) {
dp[u][1]=dp[u][2]=dp[u][3]=0;
set<int> :: iterator it1,it2,it3;
it1=gym[1].find(u);
it2=gym[2].find(u);
it3=gym[3].find(u);
if(it1 != gym[1].end()) dp[u][1]=1;
if(it2 != gym[2].end()) dp[u][2]=1;
if(it3 != gym[3].end()) dp[u][3]=1;
for(int i=0;i<hh[u].size();++i) {
int v=hh[u][i].first;
if(v==f) continue;
dfs(v,u);
dp[u][1]+=dp[v][1];
dp[u][2]+=dp[v][2];
dp[u][3]+=dp[v][3];
}
return ;
}
double ans=0;
void dfsans(int u,int f) {
for(int i=0;i<hh[u].size();++i) {
int v=hh[u][i].first;
if(v==f) continue;
ans+=hh[u][i].second*(((dp[1][1]-dp[v][1])*1.0)/(dp[1][1]*1.0)) * ((dp[v][2]*1.0)/(dp[1][2]*1.0)) * ((dp[v][3]*1.0)/(dp[1][3]*1.0));
ans+=hh[u][i].second*(((dp[1][2]-dp[v][2])*1.0)/(dp[1][2]*1.0)) * ((dp[v][1]*1.0)/(dp[1][1]*1.0)) * ((dp[v][3]*1.0)/(dp[1][3]*1.0));
ans+=hh[u][i].second*(((dp[1][3]-dp[v][3])*1.0)/(dp[1][3]*1.0)) * ((dp[v][2]*1.0)/(dp[1][2]*1.0)) * ((dp[v][1]*1.0)/(dp[1][1]*1.0));
int temp1=dp[1][1]-dp[v][1];
int temp2=dp[1][2]-dp[v][2];
int temp3=dp[1][3]-dp[v][3];
ans+=hh[u][i].second*((dp[v][1]*1.0)/(dp[1][1]*1.0)) * ((temp2*1.0)/(dp[1][2]*1.0)) * ((temp3*1.0)/(dp[1][3]*1.0));
ans+=hh[u][i].second*((dp[v][2]*1.0)/(dp[1][2]*1.0)) * ((temp1*1.0)/(dp[1][1]*1.0)) * ((temp3*1.0)/(dp[1][3]*1.0));
ans+=hh[u][i].second*((dp[v][3]*1.0)/(dp[1][3]*1.0)) * ((temp2*1.0)/(dp[1][2]*1.0)) * ((temp1*1.0)/(dp[1][1]*1.0));
dfsans(v,u);
}
return ;
}
int main() {
int n;
scanf("%d",&n);
for(int i=1;i<n;++i) {
int x,y;double d;
scanf("%d %d %lf",&x,&y,&d);
hh[x].push_back(mmp(y,d));
hh[y].push_back(mmp(x,d));
}
for(int i=1;i<=3;++i) {
int m; scanf("%d",&m);
for(int j=1;j<=m;++j) {
int x; scanf("%d",&x);
gym[i].insert(x);
}
}
ans=0.0;
dfs(1,0);
dfsans(1,0);
printf("%.8lf",ans);
return 0;
}