zoukankan      html  css  js  c++  java
  • day45-李天晓

    T1 CF512D Fox And Travelling

    • 给定一张 n 个点 m 条边的无向图。
    • 一个点只有当与它直接相连的点中最多只有一个点未被遍历过时才可被遍历。
    • 询问对于每个 (k in [0,n]),遍历 k 个点的方案数。
    • (n le 100,m le frac{n(n-1)}{2}) ,答案对 (10^9+9) 取模

    solution

    明确一点,环上的点是不可能被遍历到的。

    所以,第一步就是处理出所有的能被遍历到的点。

    然后,考虑去掉了环,那么剩下的这些树(剩下的一定是树)中树分两种,

    一种是所有的点都能被遍历到,另一种是它的根与环上的某一点相连,那么根只能最后被遍历到,

    于是设计一个dp , (dp[x][i]) 表示 x的子树中选择i个点方案数。

    (dp[x][j+k] = dp[x][j] * dp[v][k] * C(j + k , j))

    对于第二种树,显然只能以与环上相连的点为根,第一种树可以以所有的点为根进行一次dp,之后再减去算重的,

    令tot为总个数,那么选i个就会被算tot - i次。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N = 105 , mod = 1e9+9;
    inline int read()
    {
    	register int x = 0 , f = 0; register char c = getchar();
    	while(c < '0' || c > '9') f |= c == '-' , c = getchar();
    	while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48) , c = getchar();
    	return f ? -x : x;
    }
    int n , m , rot;
    int du[N] , ail[N] , vis[N] , now[N] , siz[N] , C[N][N] , f[N][N] , inv[N];
    vector<int> G[N] , tmp;
    
    void topsort()
    {
    	static queue<int> q;
    	for(int i = 1 ; i <= n ; ++i) if(du[i] <= 1) q.push(i) , ail[i] = 1;
    	while(q.size())
    	{
    		int x = q.front(); q.pop();
    		for(auto v : G[x]) if(!ail[v] && (--du[v]) <= 1) ail[v] = 1 , q.push(v);
    	}
    }
    
    void Getroot(int x , int fa)
    {
    	vis[x] = 1; tmp.push_back(x);
    	for(auto v : G[x]) if(v != fa) if(!ail[v]) rot = x; else Getroot(v , x);
    }
    
    void calc(int u , int v)
    {
    	static int tmp[N]; memset(tmp , 0 , sizeof tmp);
    	for(int i = 0 ; i <= n ; ++i)
    		for(int j = 0 ; i + j <= n ; ++j)
    			tmp[i+j] = (tmp[i+j] + (LL)f[u][i] * f[v][j] % mod * C[i+j][i] % mod) % mod;
    	for(int i = 0 ; i <= n ; ++i) f[u][i] = tmp[i];
    }
    
    void dfs(int x , int fa)
    {
    	memset(f[x] , 0 , sizeof f[x]);
    	f[x][0] = siz[x] = 1;
    	for(auto v : G[x]) if(v != fa && ail[v]) dfs(v , x) , siz[x] += siz[v] , calc(x , v);
    	f[x][siz[x]] = f[x][siz[x] - 1];
    }
    
    int main()
    {
    	n = read(); m = read();
    	for(int i = 1 , u , v; i <= m ; ++i)
    		du[u = read()]++ , du[v = read()]++ , G[u].push_back(v) , G[v].push_back(u);
    	topsort(); f[0][0] = 1;
    	for(int i = 0 ; i <= n ; ++i)
    	{
    		C[i][i] = C[i][0] = 1;
    		for(int j = 1 ; j < i ; ++j) C[i][j] = ((LL)C[i-1][j] + C[i-1][j-1]) % mod;
    	}
    	inv[0] = inv[1] = 1;
    	for(int i = 2 ; i <= n ; ++i) inv[i] = ((LL)mod - mod / i) * inv[mod % i] % mod;
    	for(int i = 1 ; i <= n ; ++i) if(!vis[i] && ail[i])
    	{
    		rot = -1; tmp.clear(); Getroot(i , 0);
    		if(~rot)
    			dfs(rot , 0) , calc(0 , rot);
    		else
    		{
    			int tot = tmp.size(); memset(now , 0 , sizeof now);
    			for(auto v : tmp)
    			{
    				dfs(v , 0);
    				for(int j = 0 ; j <= n ; ++j) now[j] = ((LL)now[j] + f[v][j]) % mod;
    			}
    			for(int j = 0 ; j <= tot ; ++j) now[j] = (LL)now[j] * inv[tot - j] % mod;
    			memset(f[tmp[0]] , 0 , sizeof f[tmp[0]]);
    			for(int j = 0 ; j <= tot ; ++j) f[tmp[0]][j] = now[j];
    			calc(0 , tmp[0]);
    		}
    	}
    	for(int i = 0 ; i <= n ; ++i) cout << f[0][i] << '
    ';
    	return 0;
    }
    
  • 相关阅读:
    关于 数据文件自增长 的一点理解
    Oracle 9i 升级后 OLAP Catalog 组件 Invalid
    Linux 查看软件位置的命令
    Oracle RAC + Data Guard 环境搭建
    Oracle 9.2.0.8 ODCIXXX 对象无效
    Oracle 9.2.0.8 ODCIXXX 对象无效
    Oracle 索引可以比表大
    Oracle Data Guard 环境下的数据库升级方法
    RAC ONS 不能启动
    Unix 和 Linux 双机热备 概念
  • 原文地址:https://www.cnblogs.com/R-Q-R-Q/p/13140042.html
Copyright © 2011-2022 走看看