zoukankan      html  css  js  c++  java
  • [CF543D]Road Improvement

    题目大意:给定一个无根树,给每条边黑白染色,求出每个点为根时,其他点到根的路径上至多有一条黑边的染色方案数,模$1e9+7$。

    题解:树形$DP$不难想到,记$f_u$为以$1$为根时,以$u$为根的子树的方案数,$f_u=prodlimits_{vin son_u}(f_v+1)$

    换根也很简单。

    但是这题卡模数,换根时要求逆元,其中$f_u$可能等于$1e9+6$,加一后变成$0$,无法求逆。可以求前缀积和后缀积转移

    卡点:原$dp$写错

    C++ Code:

    #include <cstdio>
    #include <vector>
    #include <cctype>
    namespace R {
    	int x, ch;
    	inline int read() {
    		ch = getchar();
    		while (isspace(ch)) ch = getchar();
    		for (x = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) x = x * 10 + (ch & 15);
    		return x;
    	}
    }
    using R::read;
    
    #define maxn 200010
    const int mod = 1e9 + 7;
    int head[maxn], cnt;
    struct Edge {
    	int to, nxt;
    } e[maxn << 1];
    inline void add(int a, int b) {
    	e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
    }
    
    int n;
    int f[maxn], g[maxn], ans[maxn], l[maxn], r[maxn];
    void dfs(int u, int fa = 0) {
    	f[u] = 1;
    	for (int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].to;
    		if (v != fa) {
    			dfs(v, u);
    			f[u] = static_cast<long long> (1 + f[v]) * f[u] % mod;
    		}
    	}
    }
    void dfs1(int u, int fa = 0) {
    	std::vector<int> S;
    	for (int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].to;
    		if (v != fa) S.push_back(v);
    	}
    	if (S.size()) {
    		l[*S.begin()] = g[u];
    		for (std::vector<int>::iterator it = S.begin() + 1; it != S.end(); it++) {
    			l[*it] = static_cast<long long> (l[*(it - 1)]) * (f[*(it - 1)] + 1) % mod;
    		}
    		r[*(S.end() - 1)] = 1;
    		if (S.begin() + 1 != S.end()) {
    			for (std::vector<int>::iterator it = S.end() - 2; true; it--) {
    				r[*it] = static_cast<long long> (r[*(it + 1)]) * (f[*(it + 1)] + 1) % mod;
    				if (it == S.begin()) break;
    			}
    		}
    	}
    	for (int i = head[u]; i; i = e[i].nxt) {
    		int v = e[i].to;
    		if (v != fa) {
    			g[v] = (static_cast<long long> (l[v]) * r[v] + 1) % mod; 
    			ans[v] = static_cast<long long> (g[v]) * f[v] % mod;
    			dfs1(v, u);
    		}
    	}
    }
    
    int main() {
    	n = read();
    	for (int i = 1, x; i < n; i++) {
    		x = read();
    		add(i + 1, x);
    		add(x, i + 1);
    	}
    	dfs(1);
    	ans[1] = f[1]; g[1] = 1;
    	dfs1(1);
    	for (int i = 1; i <= n; i++) {
    		printf("%d", ans[i]);
    		putchar(i == n ? '
    ' : ' ');
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    你会做夹具吗?(一)
    DDR3布线设计要点总结
    PCB设计要点-DDR3布局布线技巧及注意事项
    走进JEDEC,解读DDR(下)
    [转]关于STM32 PB3 PB4 如何设置成普通GPIO的配置
    [转]Verilog有符号数与无符号数作运算
    [转]实用光电二极管pd的采样电路
    STM32外部8M晶振不启动
    ALTCLKCTRL核的作用
    [转]如何在Altium Designer中将PCB生成PDF?
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/9903996.html
Copyright © 2011-2022 走看看