zoukankan      html  css  js  c++  java
  • 2020威海ccpc C Rencontre 树上dp染色问题

    题面

    这题面太毒瘤了

    给n个点,n-1条边,组成一个树,三个人选其中的m1个点,m2个点,m3个点。然后三个人随便选一个地方住下,然后第二天到某一个点集合,是最小路径,求期望路径是多少

    第二个样例

    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
    

    第二个人和第三个人重复了1,然后模拟比赛的时候翻译说不能同一家,然后样例一直输不对。。。赛后看题解,直接除以(m1 * m2 * m3)即可,不需要找重复……

    就这句话直接把我们的翻译看懵了,然后手算样例算不对,笑死。

    They decide to stay in separate hotels at night and meet in one hotel the next day. 
    

    思路

    其实是一道很经典的树上求贡献染色图(?)如果不知道这个可以看一下这篇博客

    然后我的思路就是跑一边,然后求每个边做的贡献,把第1,2,3人当作红黄蓝染色

    贡献就是:
    (红左个数 * 黄右个数 * 蓝右个数 +

    黄左个数 * 红右 个数* 蓝右个数 +

    蓝左个数 * 黄右个数 * 红右个数 +

    红左个数 * 黄左个数 * 蓝右个数 +

    黄左个数 * 红右个数 * 蓝左个数 +

    蓝左个数 * 黄右个数 * 红左个数)/m1/m2/m3 * 边长

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 2e5+9;
    int n;
    int ne[N<<1],to[N<<1],head[N],dis[N<<1],tot,yans[N][3];
    ll sz[N][3];
    int k[3];
    double ans;
    void inint(){
        tot=0;memset(head,-1,sizeof(head));
    }
    void add(int u,int v,int w){
        ne[tot]=head[u];
        to[tot]=v;
        dis[tot]=w;
        head[u]=tot++;
    }
    void dfs(int u,int fa){
        for(int i=0;i<3;i++){
            sz[u][i]=(ll)yans[u][i];
        }
        for(int i=head[u];~i;i=ne[i]){
            int v=to[i];if(v==fa)continue;
            dfs(v,u);
            for(int i=0;i<3;i++){
                sz[u][i]+=sz[v][i];
            }
        }
        for(int i=head[u];~i;i=ne[i]){
            int v=to[i];if(v==fa)continue;
            ll sum=0;
            sum+=(sz[v][0]*(k[1]-sz[v][1])*(k[2]-sz[v][2]))+(sz[v][1]*(k[0]-sz[v][0])*(k[2]-sz[v][2]));
            sum+=(sz[v][2]*(k[1]-sz[v][1])*(k[0]-sz[v][0]))+(sz[v][2]*sz[v][0]*(k[1]-sz[v][1]));
            sum+=(sz[v][0]*sz[v][1]*(k[2]-sz[v][2]))+(sz[v][2]*sz[v][1]*(k[0]-sz[v][0]));
           // cout<<u<<v<<(sum*dis[i]/(double)k[0]/(double)k[1]/(double)k[2])<<endl;
            ans+=((sum*1.0/(double)k[0]/(double)k[1]/(double)k[2])*(double)dis[i]);
        }
    }
    int main(){
        inint();
        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);add(v,u,w);
        }
        ans=0.0;
        for(int i=0;i<3;i++){
            scanf("%d",&k[i]);
            for(int j=0;j<k[i];j++){
                int num;scanf("%d",&num);
                yans[num][i]=1;
            }
        }
        dfs(1,0);
        printf("%f
    ",ans);
        return 0;
    }
    

    小声哔哔一句,威海这人均4题,太猛了吧。。。模拟赛的时候各种wa飞,磕磕碰碰的4题……C题题面和样例解释不了,G题线段树不会写,但赛后补了一下哈希线段树,tml

  • 相关阅读:
    System.DateUtils 1. DateOf、TimeOf 简单修饰功能
    Servlet高级
    Servlet基础
    AOP的基本概念
    Bean的定义及作用域的注解实现
    Bean
    centos7系统下,配置学校客户端网络记录
    CUDA并行编程思维过程
    CUDA(GPU)OPENCV
    3-决策树
  • 原文地址:https://www.cnblogs.com/luoyugongxi/p/13887399.html
Copyright © 2011-2022 走看看