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

    [HNOI2015]落忆枫音

    题目大意:给定一个拓扑图,然后加一条边,求加边后的以1点为根的外向生成树数目。

    试题分析

    题目真(和谐)长。。
    首先肯定先考虑在一个拓扑图中如何求外向生成树个数:
    对于每一个点((2leq ileq n)),很显然它一定要有一条入边,这样在只有1为入度为0的拓扑图中一定可以形成一棵树。
    那么第一部分就是:$prod_{i=2}^n degree_i ( 然后因为在加一条边后这个拓扑图可能变成有环的图,这样怎么办呢? 这道题很明显加一条边的目的之一就是让你来倒着想的。。。 也就是答案=总方案数(第一部分)-带环的方案数(第二部分) 既然带环,并且有边)x o y(,那么一定有路径)y o x(。 确定一个环以后剩下的点依旧可以随便连。 那么设点集)S(为)y o x(的一条路径上的点集。 于是第二部分答案=)sum_Sprod {j ot in S,1leq jleq n} degree_j( 这一部分就可以)dp(出来,设)f_i(表示从)y o i(的路径的上面的答案。 那么有转移:)f_i=frac{sum{i o j} f_j}{degree_i}$
    然后最后减去(f[X])就可以了。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    //#include<ctime>
    //#include<cmath>
    #include<queue>
     
    using namespace std;
    #define LL long long
     
    inline LL read(){
        LL x=0,f=1; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const LL INF = 2147483600;
    const LL MAXN = 300010;
    const LL Mod = 1000000007;
     
    LL N,M,X,Y; LL deg[MAXN+1]; LL cnt;
    LL Node[MAXN<<1],Next[MAXN<<1],Root[MAXN+1];
    inline void insert(LL u,LL v){
        Node[++cnt]=v; Next[cnt]=Root[u]; Root[u]=cnt;
    } LL sta[MAXN+1],top; LL f[MAXN+1];
    LL inv[MAXN+1]; LL ans=1,in[MAXN+1];
    vector<LL> vec[MAXN+1];
     
    inline LL Top_sort(){
        for(LL i=2;i<=N;i++) if(!deg[i]) {
            puts("0"); exit(0);
        } else in[i]=deg[i]; queue<LL> que; que.push(1); bool flag=false;
        f[Y]=ans; 
        while(!que.empty()){
            LL k=que.front(); sta[++top]=k; que.pop(); 
            f[k]=f[k]*inv[deg[k]+(Y==k)]%Mod;
            for(LL x=Root[k];x;x=Next[x]){
                LL v=Node[x]; --in[v]; (f[v]+=f[k])%=Mod;
                if(!in[v]) que.push(v);
            }
        } 
        return f[X];
    }
     
    int main(){
        //freopen(".in","r",stdin);
        //freopen(".out","w",stdout);
        N=read(),M=read(),X=read(),Y=read(); inv[1]=1;
        for(LL i=2;i<=max(N,M);i++) inv[i]=((Mod-(Mod/i))*inv[Mod%i])%Mod;
        for(LL i=1;i<=M;i++){
            LL u=read(),v=read();
            insert(u,v); ++deg[v]; vec[v].push_back(u);
        } for(LL i=2;i<=N;i++) ans=ans*(deg[i]+(i==Y))%Mod;
        if(Y==1) {printf("%lld
    ",ans); return 0;}
        printf("%lld
    ",(ans-Top_sort()+Mod)%Mod);
        return 0;
    }
    
  • 相关阅读:
    stylelint 安装配置
    使用 jest 测试 react component 的配置,踩坑。
    互联网媒体类型 MIME Type
    react-router 父子路由同时要接收 params 的写法
    fixed 相对于父容器定位
    react 点击空白处隐藏弹出层
    canvas 使用 isPointInPath() 判断鼠标位置是否在绘制的元素上
    JavaScript 缓存基本原理
    简单说明 Virtual DOM 为啥快
    通过阻止 touchstart 事件,解决移动端的 BUG
  • 原文地址:https://www.cnblogs.com/wxjor/p/9641442.html
Copyright © 2011-2022 走看看