zoukankan      html  css  js  c++  java
  • [HNOI2015]落忆枫音

    https://zybuluo.com/ysner/note/1109824


    题面

    给一DAG,问加上一条边后以(1)为起点的生成树的方案数。

    解析

    考虑到每个点父亲的唯一性,对于一个单纯的DAG,(ans=prod_{i=1}^n in[i])(in[i])表示(i)点的入度).
    现在加了一条边((x,y)),有可能出现环,于是我们要减去有环的情况。设环上的点为(a_1,a_2...a_k),于是该情况方案数为(frac{ans}{prod_{i=1}^kin[a_i]})(即环上点父亲固定,其它点任选)。
    怎么统计呢?
    (dp[i])表示从(y)(i)的路径上上面式子的值,则(dp[i]=frac{1}{in[i]}sum dp[j](jin i的未统计的邻点))这就是一个累乘的过程)
    我们可以建反向边,从(x)出发(这样能证明其为环),找到(y)后回溯返回(frac{ans}{in[y]}),否则返回(0),最后答案在(dp[x])里。
    答案为(prod_{i=1}^n in[i]-dp[x])

    il void dfs(re int u)
    {
      if(vis[u]) return;vis[u]=1;
      if(u==y) {dp[u]=1ll*sum*ksm(in[u],mod-2)%mod;return;}
      for(re int i=h[u];i+1;i=e[i].next)
        {
          re int v=e[i].to;
          dfs(v);
          dp[u]=(dp[u]+dp[v])%mod;
        }
      dp[u]=1ll*dp[u]*ksm(in[u],mod-2)%mod;
    }
    int main()
    {
      memset(h,-1,sizeof(h));
      n=gi();m=gi();x=gi();y=gi();
      fp(i,1,m)
        {
          re int u=gi(),v=gi();
          add(v,u);in[v]++;
        }
      ++in[1];//!!!!!!!
      fp(i,1,n)
        {
          if(i==y) ans=1ll*ans*(in[i]+1)%mod;
          else ans=1ll*ans*in[i]%mod;
          sum=1ll*in[i]*sum%mod;
        }
      dfs(x);
      printf("%lld
    ",(1ll*mod+ans-dp[x])%mod);
      return 0;
    }
    
  • 相关阅读:
    redis 学习笔记
    导数据方法
    数据库常用操作
    zepto.js
    shopnc
    vue.js
    laravel
    mysql进阶学习
    Python基础------生成器表达式形式、面向过程编程、内置函数部分
    Python基础----生成器、三元表达式、列表生成式、生成器表达式
  • 原文地址:https://www.cnblogs.com/yanshannan/p/8809119.html
Copyright © 2011-2022 走看看