题意:

​ 给出一棵\(n\)个点的树,需要加\(m\)条边,每条边脱落的概率为\(p_{i}\) ,求加入的边在最后形成图中仅在一个简单环上的边数的期望;

\(1 \le n \ , m \le 10^6\)

题解:

  • 考虑每一条边的贡献是\((1-p_{i})*\Pi_{j}p_{j}(j!=i)\),这里\(j\)和\(i\)不能同时加入;

  • 一条加入的边可以看成一条树上路径 ,即求所有和路径\(i\)相交的路径\(j\)的\(p_{j}\)的乘积;

  • 将一条树上的链\((u,v)\)拆成两条\((u,lca)\)和\((v,lca)\);

  • 这样会算重复\(i\)和\(j\)的两条链都相交的情况,但是这样\((u,lca)\)上\(lca\)的儿子是唯一的,\(v\)同理,\(hash\)去掉多算的部分;

  • 考虑一条路径\((u,v) dep[u]<dep[v]\),考虑一个点的子树里向上有长度为\(2\)的链的个数,简单容斥预处理出在\(v\)的子树里但不在\((u,v)\)上的点对答案的贡献;

  • 在\((u,v)\)上的点直接每条链在最下端打标记即可;

  • 时间复杂度:O(\(nlog \ n\))

    #include<bits/stdc++.h>
    #define ll long long
    #define mod 998244353
    using namespace std;
    const int N=1000010;
    int n,m,o=1,hd[N],a[N],b[N],ia[N],ans[N];
    int fa[N][21],bin[21],dep[N],cnt,tot;
    int s1[N],s2[N],s3[N];
    ll s4[N];
    struct Edge{int v,nt;}E[N<<1];
    struct data{
    int u,v,w,id;
    }A[N],B[N<<1];
    int pw(int x,int y){
    int re=1;
    while(y){
    if(y&1)re=(ll)re*x%mod;
    y>>=1;x=(ll)x*x%mod;
    }
    return re;
    }//
    void adde(int u,int v){
    E[o]=(Edge){v,hd[u]};hd[u]=o++;
    E[o]=(Edge){u,hd[v]};hd[v]=o++;
    }//
    char gc(){
    static char*p1,*p2,s[1000000];
    if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
    return(p1==p2)?EOF:*p1++;
    }//
    int rd(){
    int x=0;char c=gc();
    while(c<'0'||c>'9')c=gc();
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();
    return x;
    }//
    const int sz=1234651;
    struct HASH{
    int o,U[N],V[N],w[N],hd[sz],nt[N];
    int ask(int u,int v){
    if(u>v)swap(u,v);
    int x = ((ll)u*mod+v)%sz;
    for(int i=hd[x];i;i=nt[i]){
    if(U[i]==u&&V[i]==v)return w[i];
    }
    return 1;
    }
    void upd(int u,int v,int y){
    if(u>v)swap(u,v);
    int x = ((ll)u*mod+v)%sz;
    for(int i=hd[x];i;i=nt[i]){
    if(U[i]==u&&V[i]==v){w[i]=(ll)w[i]*y%mod;return;}
    }
    nt[++o]=hd[x];hd[x]=o;U[o]=u,V[o]=v;w[o]=y;
    }
    }H;//
    void dfs1(int u,int F){
    dep[u]=dep[fa[u][0]=F]+1;
    for(int i=1;bin[i]<dep[u];++i)fa[u][i]=fa[fa[u][i-1]][i-1];
    for(int i=hd[u];i;i=E[i].nt){
    int v=E[i].v;
    if(v==F)continue;
    dfs1(v,u);
    }
    }//
    int go(int u,int d){
    for(int i=0;i<20&&d;++i)if(d&bin[i])d^=bin[i],u=fa[u][i];
    return u;
    }//
    int lca(int u,int v){
    if(dep[u]<dep[v])swap(u,v);
    u=go(u,dep[u]-dep[v]);
    if(u==v)return u;
    for(int i=19;~i;--i)if(fa[u][i]!=fa[v][i])u=fa[u][i],v=fa[v][i];
    return fa[u][0];
    }//
    void dfs2(int u,int F){
    for(int i=hd[u];i;i=E[i].nt){
    int v=E[i].v;
    if(v==F)continue;
    dfs2(v,u);
    s2[u]=(ll)s2[u]*s2[v]%mod;
    s3[u]=(ll)s3[u]*s2[v]%mod;
    s4[u]=(s4[u]+s4[v]);
    }
    }//
    void dfs3(int u,int F){
    for(int i=hd[u];i;i=E[i].nt){
    int v=E[i].v;
    if(v==F)continue;
    s1[v]=(ll)s1[u]*s1[v]%mod;
    s2[v]=(ll)s2[u]*s2[v]%mod;
    s3[v]=(ll)s3[u]*s3[v]%mod;
    s4[v]=(s4[u]+s4[v]);
    dfs3(v,u);
    }
    }//
    inline int cal1(int u,int v){return (ll)s1[u]*pw(s1[v],mod-2)%mod;}
    inline int cal2(int u,int v){return (ll)s2[u]*pw(s2[v],mod-2)%mod;}
    inline int cal3(int u,int v){return (ll)s3[u]*pw(s3[v],mod-2)%mod;}
    inline ll cal4(int u,int v){return s4[u]-s4[v];}
    //
    int main(){
    freopen("cactus.in","r",stdin);
    freopen("cactus.out","w",stdout);
    n=rd();m=rd();
    for(int i=bin[0]=1;i<=20;++i)bin[i]=bin[i-1]<<1;
    for(int i=1;i<n;++i)adde(rd(),rd());
    dfs1(1,0);
    for(int i=1;i<=max(n,m);++i){ans[i]=s1[i]=s2[i]=s3[i]=1;}
    for(int i=1,u,v,w,p,q;i<=m;++i){
    u=rd();v=rd();w=lca(u,v);
    a[i]=rd();ia[i]=pw(a[i],mod-2);
    b[i]=(1+mod-a[i])%mod;
    if(!a[i]){
    s4[u]++;s4[v]++;s4[w]-=2;
    if(u!=w){
    p=go(u,dep[u]-dep[w]-1);
    B[++cnt]=(data){u,w,p,i};
    }
    if(v!=w){
    q=go(v,dep[v]-dep[w]-1);
    B[++cnt]=(data){v,w,q,i};
    }
    if(u!=w&&v!=w){
    A[++tot]=(data){p,q,0,i};
    }
    continue;
    }//
    if(u!=w){
    p=go(u,dep[u]-dep[w]-1);
    B[++cnt]=(data){u,w,p,i};
    s1[u]=(ll)s1[u]*a[i]%mod;
    s2[u]=(ll)s2[u]*a[i]%mod;
    s2[p]=(ll)s2[p]*ia[i]%mod;
    }
    if(v!=w){
    q=go(v,dep[v]-dep[w]-1);
    B[++cnt]=(data){v,w,q,i};
    s1[v]=(ll)s1[v]*a[i]%mod;
    s2[v]=(ll)s2[v]*a[i]%mod;
    s2[q]=(ll)s2[q]*ia[i]%mod;
    }
    if(u!=w&&v!=w){
    A[++tot]=(data){p,q,0,i};
    H.upd(p,q,ia[i]);
    }
    }
    dfs2(1,0);
    dfs3(1,0);
    for(int i=1;i<=tot;++i){
    int u=A[i].u,v=A[i].v;
    ans[A[i].id]=(ll)ans[A[i].id]*H.ask(u,v)%mod;
    }
    for(int i=1;i<=cnt;++i){
    int u=B[i].u,v=B[i].v,w=B[i].w,now=1;
    now=cal3(u,v);
    now=(ll)now*pw(cal2(u,w),mod-2)%mod;
    now=(ll)now*cal1(u,v)%mod;
    ans[B[i].id]=(ll)ans[B[i].id]*now%mod;
    int t = cal4(u,v);
    if(!a[B[i].id])t-=dep[u]-dep[v];
    if(t)ans[B[i].id]=0;
    }
    int Ans=0;
    for(int i=1;i<=m;++i){
    ans[i] = (ll)ans[i]*b[i]%mod;
    if(a[i])ans[i] = (ll)ans[i]*pw(a[i],mod-2)%mod;
    Ans=(Ans+ans[i])%mod;
    }
    cout<<Ans<<endl;
    return 0;
    }

【纪中集训2019.3.12】Mas的仙人掌的更多相关文章

  1. 【纪中集训2019.3.12】Z的礼物

    题意 已知\(a_{i} = \sum_{j=1}^{i} \{^{i} _{j} \}b_{j}\), 给出\(a_{1} 到 a_{n}\) : 求\(b_{l} 到 b_{r}\)在\(1e9+ ...

  2. 【纪中集训2019.3.27】【集训队互测2018】小A的旅行(白)

    题目 描述 ​ \(0-n-1\)的图,满足\(n\)是\(2\)的整数次幂, $ i \to j $ 有 $ A_{i,j} $ 条路径: ​ 一条路径的愉悦值定义为起点和终点编号的\(and\)值 ...

  3. 【纪中集训2019.3.23】Deadline

    题意 描述 一个二分图\((A,B)\),每个点额外有一个颜色0或者1: 匹配时,只能相同颜色的点匹配: 给出\(A\)中的颜色,问如何分配\(B\)种的颜色使得\((A,B)\)的最大匹配最小: 范 ...

  4. 【纪中集训2019.3.23】IOer

    题目 描述 你要在\(m\)天内,刷\(n\)道题,每天可以刷的题的数目不限: 第\(i\)天可以刷的题目的种类是\(ui+v\): 两种刷题的方案不同当且仅当某天刷题的数量不同或者依次刷题的种类不同 ...

  5. 【纪中集训2019.3.11】Cubelia

    题目: 描述 给出长度为\(n\)的数组\(a\)和\(q\)个询问\(l,r\). 求区间\([l,r]\)的所有子区间的前缀和的最大值之和: 范围: $n \le 2 \times 10^5 , ...

  6. 【纪中集训2019.3.13】fft

    题意: 描述 一共有\(n+m\)道题,其中\(n\)道答案是\(A\),\(m\)道答案是\(B\): 你事先知道\(n和m\),问在最优情况下的期望答错次数,对\(998244353\)取模: 范 ...

  7. 「中山纪中集训省选组D1T1」最大收益 贪心

    题目描述 给出\(N\)件单位时间任务,对于第\(i\)件任务,如果要完成该任务,需要占用\([S_i, T_i]\)间的某个时刻,且完成后会有\(V_i\)的收益.求最大收益. 澄清:一个时刻只能做 ...

  8. 纪中集训 Day 2

    今天(其实是昨天= =)早上起来发现好冷好冷啊= = 吃完饭就准备比赛了,好吧B组难度的题总有一道不知到怎么写QAQ 太弱了啊!!! 蒟蒻没人权啊QAQ 今天第4题不会写,在这里说说吧 题目的意思就是 ...

  9. 纪中集训 Day1

    今天早上起来吃饭,发现纪中伙食真的是太差了!!!什么都不热,早餐的面包还好,然后就迎来了美好的早晨= = 早上做一套题,T1T2果断秒,T3一看就是noi原题,还好看过题解会写,然后就愉快的码+Deb ...

随机推荐

  1. Python-RabbitMQ(简单发送模型)

    RabbitMQ需要 erlang 和pika 1.RabbitMQ和erlang版本必须匹配,否则就报没有进程错误 2.RabbitMQ的erlang.cookie和windows下的erlang. ...

  2. sqli-labs学习笔记 DAY4

    DAY 4 sqli-labs lesson 23 与lesson 1一样,只不过屏蔽了#和–注释符. 报错型注入: 爆库:id=99' UNION SELECT 1,extractvalue(1,c ...

  3. python 原生态调用server服务————SimpleHTTPServer

    python 原生态调用server服务,接收http传递的参数并且处理返回结果 很多blog中都是抄了官网的,没有说明参数如何接收 1.代码中提供了post与get两种方式来发起请求,但是传递参数时 ...

  4. SpringBoot初始教程之Redis集中式Session管理

    1.介绍 有关Session的管理方式这里就不再进行讨论,目前无非就是三种单机Session(基于单机内存,无法部署多台机器).基于Cookie(安全性差).基于全局的统一Session管理(redi ...

  5. 第一个scrim任务分布

    一.项目经理:郭健豪 二.scrim分工 杨广鑫.郭健豪:制作第一个精选页面布局,和代码实现.如:实现图书推荐布局中图书的排布,搜索框代码的实现,消息提示的跳转 李明.郑涛:实现第一个精选页面数据库的 ...

  6. 进阶系列(4)—— C#文件与流

    一. 驱动器 在Windows操作系统中,存储介质统称为驱动器,硬盘由于可以划分为多个区域,每一个区域称为一个驱动器..NET Framew   ork提供DriveInfo类和 DriveType枚 ...

  7. bata7

    目录 组员情况 组员1:胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:恺琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:何宇恒 组员11:刘一好 展示组内最新 ...

  8. 【TCP/IP详解 卷一:协议】第六章:DHCP 和自动配置

    简介 为了使用 TCP/IP 协议族,每台主机or路由器都需要一定的配置信息: IP地址 子网掩码 广播地址 路由或转发表 DNS 协议配置方法: 手动 通过使用网络服务来获得 使用一些算法来自动确定 ...

  9. 程序开发入门工具之CodeBlocks

    程序开发基础工具之CodeBlocks 作为程序开发工作者,我们会接触很多的程序开发软件:但实用以及容易掌握的程序开发软件对于初学者的学习能力是有一定的加成的.今天我就作为一个程序开发者给大家推荐一个 ...

  10. 17_常用API_第17天(包装类、System、Math、Arrays、大数据运算)_讲义

    今日内容介绍 1.基本类型包装类 2.System类 3.Math类 4.Arrays类 5.大数据运算 01基本数据类型对象包装类概述 *A:基本数据类型对象包装类概述 *a.基本类型包装类的产生 ...