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

    Description

    Luogu3244
    BZOJ4011

    Solution

    如果是一个DAG,那么答案显然是

    [prod_{i=2}^n deg(i) ]

    其中(deg(i))是点(i)的入度。加上条边后可能会成环,我们要去掉成环的情况数。考虑一个环,错误的计数只会发生在环上每个点选了自己环上的父亲,环外的点随意。所以对于每个环,多余的计数是

    [prod_{i otin Circle} deg(i) ]

    而环又是一个(y)(x)的路径加上((x,y))这条边构成的。所以设(f[u])为从(u)出发到(x)的路径(假设其在环上)多余的贡献,那么有

    [f[u] = sum_{(u,v)in E} f[v] / deg[u] ]

    所以就是一个简单的记搜就行了。

    Code

    #include <cstdio>
    #include <cstring>
    
    typedef long long ll;
    const int N = 100010;
    const int M = 200010;
    const ll mod = 1e9 + 7;
    
    int hd[N], nxt[M], to[M], cnt;
    ll deg[N], f[N], inv[N], n, m;
    
    inline void adde(int x, int y) {
      to[++cnt] = y;
      nxt[cnt] = hd[x];
      hd[x] = cnt;
    }
    
    int dfs(ll x) {
      if (f[x] != -1) return f[x];
      f[x] = 0;
      for (int i = hd[x]; i; i = nxt[i]) {
        f[x] = (f[x] + dfs(to[i])) % mod;
      }
      f[x] = f[x] * inv[deg[x]] % mod;
      return f[x];
    }
    
    void calc() {
      inv[1] = 1;
      for (int i = 2; i <= n; ++i)
        inv[i] = (-mod / i * inv[mod % i] % mod + mod) % mod;
    }
    
    int main() {
      int x, y;
      scanf("%lld%lld%d%d", &n, &m, &x, &y);
      for (int i = 1, x, y; i <= m; ++i) {
        scanf("%d%d", &x, &y);
        adde(x, y);
        deg[y]++;
      }
      ll ans = 1, sum = 1;
      for (int i = 2; i <= n; ++i) {
        if (i == y) ans = ans * (deg[i]+1) % mod;
        else ans = ans * deg[i] % mod;
        sum = sum * deg[i] % mod;
      }
      memset(f, -1, sizeof f); calc(); f[x] = sum * inv[deg[x]] % mod;
      ll del = dfs(y);
      ans = (ans - del + mod) % mod;
      printf("%lld
    ", ans);
      return 0;
     }
    
  • 相关阅读:
    NET Core 2.2
    NET Core项目模板
    Eclipse同时显示多个控制台项目的输出
    Java中的序列化
    Java中的泛型
    Java中的集合
    Java中的数据结构
    Java中的包
    Java中的接口
    Java中的封装
  • 原文地址:https://www.cnblogs.com/wyxwyx/p/hnoi2015lysy.html
Copyright © 2011-2022 走看看