zoukankan      html  css  js  c++  java
  • CF512D Fox And Travelling

    Link
    首先我们进行拓扑排序,最后留下的点就是不能到达的点。
    那么把这些点去掉之后,剩下的就是一个森林,而树有两类:
    (1.)无根树:可以任意选择一个叶节点开始,然后可以在任意一个节点结束。
    (2.)有根树:根节点与某个不能到达的点相邻,那么如果要到达根节点就必须在最后到达。
    对于有根树,设(f_{i,j})表示在(i)的子树中选(j)个的方案数,合并是卷积的形式,为了表示顺序要乘上组合数。
    对于无根树,枚举强制哪个节点最后到达,然后就变成了有根树的情况。注意对于(n)个点选(m)的方案数((n e m)),一种情况会被计算(n-m)次,除掉即可。
    时间复杂度为(O(n^3))

    #include<queue>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    const int N=107,P=1000000009;
    int n,inv[N],C[N][N],deg[N],vis[N],fa[N],size[N],f[N][N],s[N],ans[N];std::vector<int>e[N],g[N];std::queue<int>q;
    int read(){int x;scanf("%d",&x);return x;}
    void inc(int&a,int b){a+=b-P,a+=a>>31&P;}
    int mul(int a,int b){return 1ll*a*b%P;}
    void dp(int u,int fa)
    {
        size[u]=0,f[u][0]=1,memset(f[u]+1,0,n<<2);
        for(int v:g[u])
        {
    	if(v==fa) continue;
    	dp(v,u),size[u]+=size[v];
    	for(int i=size[u];~i;--i) for(int j=1;j<=size[v]&&j<=i;++j) inc(f[u][i],mul(C[i][j],mul(f[u][i-j],f[v][j])));
        }
        ++size[u],f[u][size[u]]=f[u][size[u]-1];
    }
    void dfs(int u,int fa)
    {
        for(int v:g[u]) if(v^fa) dfs(v,u);
        dp(u,0);
        for(int i=0;i<=n;++i) inc(s[i],f[u][i]);
    }
    int main()
    {
        n=read(),ans[0]=inv[0]=inv[1]=1;
        for(int i=2;i<=n;++i) inv[i]=mul(P-P/i,inv[P%i]);
        for(int i=0;i<=n;++i) for(int j=C[i][0]=1;j<=i;++j) inc(C[i][j]=C[i-1][j],C[i-1][j-1]);
        for(int m=read(),u,v;m;--m) ++deg[u=read()],++deg[v=read()],e[u].push_back(v),e[v].push_back(u);
        for(int i=1;i<=n;++i) if(std::sort(e[i].begin(),e[i].end()),deg[i]<2) q.push(i);
        for(int u;!q.empty();)
        {
    	vis[u=q.front()]=1,q.pop();
    	for(int v:e[u])
    	    if(!vis[v])
    	    {
    		fa[u]=v,g[u].push_back(v),g[v].push_back(u);
    		if(--deg[v]==1) q.push(v); 
    		break;
    	    }
        }
        for(int i=1;i<=n;++i)
    	if(vis[i])
    	{
    	    if(!fa[i])
    	    {
    		memset(s,0,(n+1)<<2),dfs(i,0);
    		for(int j=0;j<=size[i];++j) s[j]=mul(inv[size[i]-j],s[j]);
    		for(int j=n;j;--j) for(int k=0;k<j;++k) inc(ans[j],mul(C[j][k],mul(s[j-k],ans[k])));
    	    }
    	    else if(!vis[fa[i]])
    	    {
    		g[i].erase(find(g[i].begin(),g[i].end(),fa[i])),dp(i,0);
    		for(int j=n;j;--j) for(int k=0;k<j;++k) inc(ans[j],mul(C[j][k],mul(f[i][j-k],ans[k])));
    	    }
    	}
        for(int i=0;i<=n;++i) printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    django如何给上传的图片重命名(给上传文件重命名)
    Nginx 常见问题解决
    nginx 出现413 Request Entity Too Large问题的解决方法
    python判断一个对象是否可迭代
    InnerClass annotations are missing corresponding EnclosingMember annotations. Such InnerClas...
    Android Studio中新建和引用assets文件
    android 登录效果
    Android (争取做到)最全的底部导航栏实现方法
    抽屉效果的导航菜单
    Android开发之自定义局部导航菜单
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12638003.html
Copyright © 2011-2022 走看看