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

    题面

    ( ext{Description:})

    给一张 (n) 割点 (m) 条边的 ({ m DAG}) ,保证点 (1)不存在入边,现在需要在({ m DAG}) 中加入一条不在原图中的边 ({ m (x,y)}) , 求这个有向图以 (1) 为根的树形图个数对 (1e9+7) 取模的结果

    (n<=100000,m<=200000)

    ( ext{Solution:})

    考虑没有加边,是 ({ m DAG}) 的情况,那么答案就是每个点的入度之积,相当于每个点选一个指向自己的点作为父亲,有入度种选法,有乘法原理:

    [{ m Ans} = prod in[x] ]

    现在有一条边加进来,如果每个点还是像原来那么随便,可能会成环,选考虑减去不合法情况。

    对于一个环,它所能“贡献”的不合法数量为

    [prod in[x] (x在环上) ]

    原因是 (x) 的父亲只选环上的边,其它的乱选,这样一定成环,一定不合法。

    所以我们把所有环的 "贡献" 减去即可。

    建反图(原来怎么乘过来,现在怎么减回去),直接在 ({ m DAG})({ m dp}) 求非法"贡献"。

    转移:

    [f[x] = frac{sum f[y]}{in[x]} (y连向x) ]

    #include <vector>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <bitset>
    #include <iostream>
    #include <assert.h>
    #include <algorithm>
    
    using namespace std;
    
    #define LL long long
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #define GO debug("GO
    ")
    
    struct Stream {
        template<typename T>
        inline T rint() {
            register T x = 0, f = 1; register char c;
            while (!isdigit(c = getchar())) if (c == '-') f = -1;
            while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getchar()));
            return x * f;
        }
        template <typename _Tp>
        Stream& operator>> (_Tp& x)
        { x = rint<_Tp>(); return *this; }
        Stream& operator<< (int x)
        { printf("%d", x); return *this;}
        Stream& operator<< (LL x)
        { printf("%lld", x); return *this;}
        Stream& operator<< (char ch)
        { putchar(ch); return *this; }
    } xin, xout;
    
    
    template<typename T> inline void chkmin(T &a, T b) { a > b ? a = b : 0; }
    template<typename T> inline void chkmax(T &a, T b) { a < b ? a = b : 0; }
    
    const int N = 1e5 + 10, P = 1e9 + 7;
    
    LL sum = 1, ans = 1;
    bitset<N> vis;
    int n, m, S, T, in[N];
    LL f[N];
    vector<int> G[N];
    
    LL qpow(LL a, LL b) {
        LL res = 1;
        for (; b; b >>= 1, a = a * a % P)
            if (b & 1) res = res * a % P;
        return res;
    }
    
    void DFS(int u) {
        if (vis[u]) 
            return;
        if (u == T) {
            f[u] = sum * qpow(in[u], P - 2) % P;
            return;
        }
        vis[u] = 1;
        for (vector<int>::iterator it = G[u].begin(); it != G[u].end(); ++ it) {
            DFS(*it);
            f[u] = (f[u] + f[*it]) % P;
        }
        f[u] = (f[u] * qpow(in[u], P - 2)) % P;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("xhc.in", "r", stdin);
        freopen("xhc.out", "w", stdout);
    #endif
        xin >> n >> m >> S >> T;
        for (register int i = 1; i <= m; ++ i) {
            int u, v;
            xin >> u >> v;
            G[v].push_back(u);
            in[v]++;
        }
        in[1]++;
        for (int i = 1; i <= n; ++ i) {
            sum = sum * in[i] % P;
            ans = ans * (in[i] + (i == T)) % P;
        }
        DFS(S);
        xout << (ans - f[S] + P) % P << '
    ';
    }
    
    
  • 相关阅读:
    [转]Kqueue与epoll机制
    [转]Docker中的镜像
    [转]linux awk命令详解
    [转]Linux Shell 1>/dev/null 2>&1 含义
    file_get_contents(): SSL operation failed with code 1...解决办法和stream_context_create作用
    PHP abstract与interface之间的区别
    PHP基于Redis的全局订单号id
    Eclipse for php+Xdebug,搭建php单步调试环境
    Eclipse launch configuration----Eclipse运行外部工具
    MySql 缓冲池(buffer pool) 和 写缓存(change buffer) 转
  • 原文地址:https://www.cnblogs.com/cnyali-Tea/p/10624310.html
Copyright © 2011-2022 走看看