zoukankan      html  css  js  c++  java
  • BZOJ 4011 HNOI2015 落忆枫音

    AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=4011

    题目很长,写得也很有诗意与浪漫色彩,让我们不禁感叹出题人是一个多么英俊潇洒的人。

    所以题目大意就是:

      给一个有向无环图,问加上一条我给定的边后,有多少个以1为根的树形图?n<=1e5,m<=2*1e5

    原图无重边,加上的边可以为自环。

      

    首先先来解决一个问题:

      一个有向无环图的树形图有多少个呢? 

    相当于除了根节点以外,每个点随意取一个入度,为什么就一棵树呢?每个点选一个父亲,并且保证没有环,所以是一棵树。

    好的,对于有向无环图就一定是这样的,那么若加入一条边<x,y>,

    那么就可能再选择的过程中选出一个环[就是祖先的父亲是自己这种情况]。那么我们就需要删去这种情况。

    首先要出现环,则必定包括了<x,y>这条边,剩下的部分是原图中y->x的一条路径,要求这条路径上的点必须选择一条路径使得构成一个环。而其它的点可以随意选。

    设F(i)表示y->i上的点所成路径必须选择一条能构成环路径的方案数。

    有初始值:

          

    递推式:

       

    相当于j可以选择延续所有从y走来的i的路径,但是要除以j原本可以选择的路径总数。

    最后答案=所有方案[入度乘积] - F(x)。

     

    听说ZZD去年就想出来了这题,不过因为不会打逆元而失之交臂[不然就是省队了?%%%]

    为什么会有逆元?...额我好像忘记说方案数要取模了...

    那么这题中为了加速运算,就用了一个O(n)递推求1...n的所有逆元的方法,我也算是普及一下吧?...

    画图的时候没太注意大小写,不要太在意...

    那么i的逆元可以由p mod i的逆元得知了,这显然是一个已知的数,所以每次递推都是O(1)的,边界:1的逆元=1。

     

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    inline int in(){
        int x=0;char ch=getchar();
        while(ch>'9' || ch<'0') ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return x;
    }
    
    const int maxn=100010;
    const int mod=1e9+7;
    typedef long long ll;
    
    struct Node{
        int data,next;
    }node[maxn<<1];
    
    #define now node[point].data
    #define then node[point].next
    
    int n,m,ans,cnt,x,y;
    int head[maxn],d[maxn],ld[maxn];
    int f[maxn],stack[maxn],top;
    int inv[maxn<<1];
    
    void init(){
        inv[1]=1;
        for(int i=2;i<=m;i++)
            inv[i]=(mod-(ll)inv[mod%i]*(mod/i)%mod)%mod;
    }
    
    void add(int u,int v){
        node[cnt].data=v;node[cnt].next=head[u];head[u]=cnt++;d[v]++;
    }
    
    int power(int a,int k){
        int ans=1;
        for(;k;k>>=1){
            if(k&1) ans=(ll)ans*a%mod;
            a=(ll)a*a%mod;
        }
        return ans;
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("maple.in","r",stdin);
        freopen("maple.out","w",stdout);
    #endif
    
        int u,v;
    
        n=in(),m=in();
        x=in(),y=in();
        init();
        for(int i=1;i<=n;i++) head[i]=-1;
        for(int i=1;i<=m;i++)
            u=in(),v=in(),add(u,v);
        d[y]++;
        ans=1;
        for(int i=2;i<=n;i++) ans=(ll)ans*d[i]%mod; 
        if(y==1){ printf("%d",ans);return 0;}
        else f[y]=(ll)ans*inv[d[y]]%mod;
        
        d[y]--;
        memcpy(ld,d,sizeof(d));
        for(int i=1;i<=n;i++) if(!d[i]) stack[++top]=i;
        
        while(top){
            u=stack[top--];
            for(int point=head[u];point!=-1;point=then){
                if(--d[now]==0)
                    stack[++top]=now;
                f[now]=(f[now]+(ll)f[u]*inv[ld[now]]%mod)%mod;
            }
        }
        
        ans=(ans-f[x]+mod)%mod;
        printf("%d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    Bootstrap 网格系统(Grid System)实例2
    Bootstrap 网格系统(Grid System)实例1
    Bootstrap 网格系统(Grid System)
    Bootstrap CSS概览
    Bootstrap响应式布局(1)
    46、谈谈你对面向对象的理解?
    算法--练习题1
    堆排序----赠品2
    计数排序----赠品1
    45、如何使用python删除一个文件?
  • 原文地址:https://www.cnblogs.com/Robert-Yuan/p/5241268.html
Copyright © 2011-2022 走看看