2020CCPC威海 C Rencontre(树形DP,期望)

44 篇文章 0 订阅
17 篇文章 0 订阅

Located at the easternmost tip of Shandon Peninsula, Weihai is one of the most famous tourist destinations all over China. There are beautiful hills, seas, bays, springs, islands, and beautiful beaches in Weihai. It is also a coastal city abundant in seafood, including prawn, sea cucumber, abalone, shellfish, and algae.

Attracted by the distinctive scenery and pleasant environment, three theoretical computer scientists plan to have a trip to Weihai. However, they cannot reach a consensus on accommodation, since some people prefer some hotels while other people like others. They decide to stay in separate hotels at night and meet in one hotel the next day. The hotel they meet may not necessarily be one of the hotels they stay in.

There are some roads connecting the hotels in Weihai. The roads are specially designed such that there is a unique path between every pair of hotels. Every theoretical computer scientist has prepared a list of candidate hotels before their trip starts. When they arrive in Weihai, each of them will uniformly and independently choose one hotel from the candidate hotel list. Also, they will meet in a hotel such that the total length of their routes is minimized. As a member of the theoretical computer science group, can you tell the expected total length of their routes?

Input Specification:
The first line of the input contains a single integer n (1≤n≤200000), denoting the number of hotels in Weihai. Then follow n−1 lines, describing the roads connecting the hotels. Each of the n−1 lines contains three integers u,v,w (1≤u,v≤n,u≠v,1≤w≤1000), denoting a road of length w connecting the hotels numbered u and v. It is guaranteed that there is a unique path between every pair of hotels.

The last three lines of the input specify the candidate hotel lists, one for each theoretical computer scientist. Each line begins with a single integer m (1≤m≤n) and m distinct integers a
​1
​​ ,a
​2
​​ ,⋯,a
​m
​​ (1≤a
​i
​​ ≤n), meaning that the candidate hotel list contains the hotels numbered a
​1
​​ ,a
​2
​​ ,⋯,a
​m
​​ .

Output Specification:
Print the expected total length of their routes within an absolute or relative error of no more than 10
​−6
​​ .

Sample Input 1:
3
1 2 1
2 3 2
1 1
1 2
1 3
Sample Output 1:
3
Sample Input 2:
5
1 2 3
1 3 5
2 4 7
2 5 11
3 2 4 5
4 1 2 3 5
2 1 3
Sample Output 2:
13.958333333333

是道银牌题,但是写了一下,发现其实不难,可惜比赛的时候都没怎么看,要是比赛的时候手速快一点就好了。。。

题意:
有3个人,每个人有一些待选点。
每个人会选择一个点,然后他们会会和到一个点,使得3人到该点距离和最小。
求3人会和的期望的距离和。

思路:
模拟一下可以发现,3人回合的距离和为 d i s ( a , b ) + d i s ( a , c ) + d i s ( b , c ) 2 \frac{dis(a,b)+dis(a,c)+dis(b,c)}{2} 2dis(a,b)+dis(a,c)+dis(b,c)
我们按照边,对于 d i s ( a , b ) , d i s ( a , c ) , d i s ( b , c ) dis(a,b),dis(a,c),dis(b,c) dis(a,b),dis(a,c),dis(b,c)分别统计贡献。
则最终期望就是 ∑ d i s ( a , b ) n u m ( a ) ∗ n u m ( b ) + ∑ d i s ( a , c ) n u m ( a ) ∗ n u m ( c ) + ∑ d i s ( b , c ) n u m ( a ) ∗ n u m ( c ) 2 \frac{\frac{∑dis(a,b)}{num(a)*num(b)}+\frac{∑dis(a,c)}{num(a)*num(c)}+\frac{∑dis(b,c)}{num(a)*num(c)}}{2} 2num(a)num(b)dis(a,b)+num(a)num(c)dis(a,c)+num(a)num(c)dis(b,c)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;
const int maxn = 2e5 + 7;

vector<pair<int,int> >G[maxn];
int vis[4][maxn];
double siz[4][maxn];
double dp[maxn][4];
double num[4];
double ans;
int n;

void dfs(int x,int fa) {
    for(int i = 0;i < 3;i++) {
        if(vis[i][x]) siz[i][x] = 1.0;
    }
    for(int i = 0;i < G[x].size();i++) {
        int v = G[x][i].first,w = G[x][i].second;
        if(v == fa) continue;
        dfs(v,x);
        //算dis(a,b)
        dp[x][0] += (double)w * siz[0][v] * (num[1] - siz[1][v]);
        dp[x][0] += (double)w * siz[1][v] * (num[0] - siz[0][v]);
        
        //算dis(a,c)
        dp[x][1] += (double)w * siz[0][v] * (num[2] - siz[2][v]);
        dp[x][1] += (double)w * siz[2][v] * (num[0] - siz[0][v]);
        
        //算dis(b,c)
        dp[x][2] += (double)w * siz[1][v] * (num[2] - siz[2][v]);
        dp[x][2] += (double)w * siz[2][v] * (num[1] - siz[1][v]);
        
        for(int j = 0;j < 3;j++) {
            siz[j][x] += siz[j][v];
        }
    }
}

int main() {
    scanf("%d",&n);
    for(int i = 1;i < n;i++) {
        int x,y,z;scanf("%d%d%d",&x,&y,&z);
        G[x].push_back({y,z});
        G[y].push_back({x,z});
    }
    double all = 1.0;
    for(int i = 0;i < 3;i++) {
        int m;scanf("%d",&m);
        all *= m;
        num[i] = m;
        for(int j = 1;j <= m;j++) {
            int x;scanf("%d",&x);
            vis[i][x] = 1;
        }
    }
    dfs(1,-1);
    for(int i = 1;i <= n;i++) {
        ans += (double)(dp[i][0] / (num[0] * num[1]) + dp[i][1] / (num[0] * num[2]) + dp[i][2] / (num[1] * num[2]));
    }
    
    
    printf("%.6f\n",ans / 2);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值