• C Rencontre CCPC 威海


    C Rencontre CCPC 威海

    给出一棵树,有三个人,每个人都一个集合,表示他们可能会选的点,当三个人确定选的点a,b, c后,d=min(dis(a,v)+dis(b,v)+dis(c,v)),求d的期望值。

    题解:

    这个题目可能会选择的点就是 三个 点的LCA的深度最小的那个点。

    然后推推题目的第二个样例可以发现就是求每一条边的贡献,然后除以最后三个人可以选择的数量的乘积。

    因为选择这个最近的点,所以可以发现三个人走到最短的点经过的边一定只会经过一次,所以其实对于一条边的经过的次数就是三个人可以选择的数量的乘积减去每一个端点的1和2和3的乘积。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 4e5+10;
    typedef long long ll;
    int head[maxn],to[maxn<<1],nxt[maxn<<1],cnt,w[maxn<<1];
    void add(int u,int v,int c){
    	++cnt,to[cnt] = v,nxt[cnt] = head[u],w[cnt] = c,head[u] = cnt;
    	++cnt,to[cnt] = u,nxt[cnt] = head[v],w[cnt] = c,head[v] = cnt;
    }
    ll have[10][maxn],sum;
    double dfsans(int u,int pre){
    	double ans = 0;
    	for(int i=head[u];i;i=nxt[i]){
    		int v = to[i];
    		if(v == pre) continue;
    		ans += dfsans(v,u);
    		ll res1 = 1,res2 = 1;
    		for(int j=1;j<=3;j++) have[j][u]+=have[j][v];
    		for(int j=1;j<=3;j++) res1 = res1 * have[j][v];
    		for(int j=1;j<=3;j++) res2 = res2 * (have[j][0]-have[j][v]);
    		ans += (sum - res2 - res1)*w[i];
    	}
    	return ans;
    }
    
    int main(){
    	int n;
    	scanf("%d",&n);
    	for(int i=1;i<n;i++){
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		add(u,v,w);
    	}
    	sum = 1;
    	for(int i=1;i<=3;i++){
    		int m,x;
    		scanf("%d",&m);
    		sum *= m,have[i][0] = m;
    		while(m--){
    			scanf("%d",&x);
    			have[i][x]++;
    		}
    	}
    	double cur = dfsans(1,0);
    	double ans = cur/(1.0*sum);
    	printf("%.9f
    ", ans);
    	return 0;
    }
    
    
  • 相关阅读:
    GhostScript命令参数详解(转)
    西安电子科技大学week02-问题规约表示及其搜索技术
    西安电子科技大学week01-状态空间表示及其问题解决
    canal同步mysql数据
    Navicat连接mysql数据库报错2003
    fieldset可以实现在虚线框中写文字
    CSS盒模型简单介绍
    js变量数组和对象常用方法
    js数组方法大全
    IIFE和闭包和let
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/13899198.html
Copyright © 2020-2023  润新知