[关闭]
@ysner 2018-04-12T17:31:13.000000Z 字数 900 阅读 2112

[HNOI2015]落忆枫音

DP 方案数


题面

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

解析

考虑到每个点父亲的唯一性,对于一个单纯的DAG,表示点的入度).
现在加了一条边,有可能出现环,于是我们要减去有环的情况。设环上的点为,于是该情况方案数为(即环上点父亲固定,其它点任选)。
怎么统计呢?
表示从的路径上上面式子的值,则这就是一个累乘的过程)
我们可以建反向边,从出发(这样能证明其为环),找到后回溯返回,否则返回,最后答案在里。
答案为

  1. il void dfs(re int u)
  2. {
  3. if(vis[u]) return;vis[u]=1;
  4. if(u==y) {dp[u]=1ll*sum*ksm(in[u],mod-2)%mod;return;}
  5. for(re int i=h[u];i+1;i=e[i].next)
  6. {
  7. re int v=e[i].to;
  8. dfs(v);
  9. dp[u]=(dp[u]+dp[v])%mod;
  10. }
  11. dp[u]=1ll*dp[u]*ksm(in[u],mod-2)%mod;
  12. }
  13. int main()
  14. {
  15. memset(h,-1,sizeof(h));
  16. n=gi();m=gi();x=gi();y=gi();
  17. fp(i,1,m)
  18. {
  19. re int u=gi(),v=gi();
  20. add(v,u);in[v]++;
  21. }
  22. ++in[1];//!!!!!!!
  23. fp(i,1,n)
  24. {
  25. if(i==y) ans=1ll*ans*(in[i]+1)%mod;
  26. else ans=1ll*ans*in[i]%mod;
  27. sum=1ll*in[i]*sum%mod;
  28. }
  29. dfs(x);
  30. printf("%lld\n",(1ll*mod+ans-dp[x])%mod);
  31. return 0;
  32. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注