zoukankan      html  css  js  c++  java
  • Codeforces 1276D. Tree Elimination(树形dp)

    https://codeforces.com/contest/1276/problem/D

    有点atcoder题的意思。

    我们肯定是不能按时间顺序考虑的。

    那么按树形dp的顺序考虑。

    考虑以(i)为根的一棵子树里的边的情况,当然可能要加上(i->fa[i])这条边。

    因为(i)的子节点的子树都做了,所以只用考虑(i->fa[i])这条边。

    可能(fa[i])的其它边在(i->fa[i])之前,且把(fa[i])选了,影响到了(i->fa[i])
    可能(i->son[i])的边在(i->fa[i])之前,且把(i)选了,影响到了(i->fa[i])
    可能(i->fa[i])(i->son[i])之前,把(i)选了,影响到了(i->son[i])

    (f[i][0/1][0/1])(i)为根子树内,第一个(0/1)表示(i->fa[i])之前的连着(fa[i])的边有没有选(fa[i]),第二个(0/1)表示出来之后(fa[i])选了没有。

    转移十分简单。

    Code:

    #include<bits/stdc++.h>
    #define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
    #define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
    #define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
    #define ll long long
    #define pp printf
    #define hh pp("
    ")
    using namespace std;
    
    const int mo = 998244353;
    
    const int N = 2e5 + 5;
    
    int n, x, y;
    int fi[N], to[N * 2], nt[N * 2], tot = 1;
    
    void link(int x, int y) {
    	nt[++ tot] = fi[x], to[tot] = y, fi[x] = tot;
    }
    
    int fa[N], fq[N];
    
    int d[N], d0;
    
    ll f[N][2][2], g[2][2], h[2][2];
    
    void dg(int x) {
    	for(int i = fi[x]; i; i = nt[i]) if(to[i] != fa[x]) {
    		int y = to[i];
    		fa[y] = x; fq[y] = i;
    		dg(y);
    	}
    	d0 = 0;
    	for(int i = fi[x]; i; i = nt[i])
    		d[++ d0] = to[i];
    	reverse(d + 1, d + d0 + 1);
    	fo(st, 0, 1) {
    		memset(g, 0, sizeof g);
    		g[0][st] = 1;
    		fo(i, 1, d0) {
    			memcpy(h, g, sizeof g);
    			memset(g, 0, sizeof g);
    			int y = d[i];
    			if(y == fa[x]) {
    				fo(u, 0, 1) fo(v, 0, 1) if(h[u][v]) {
    					if(!u && !v) {
    						g[1][0] = (g[1][0] + h[u][v]) % mo;
    						g[0][1] = (g[0][1] + h[u][v]) % mo;
    					} else {
    						g[u][v] = (g[u][v] + h[u][v]) % mo;
    					}
    				}
    			} else {
    				fo(u, 0, 1) fo(v, 0, 1) if(h[u][v]) {
    					fo(p, 0, 1) if(f[y][u][p])
    						g[p][v] = (g[p][v] + h[u][v] * f[y][u][p]) % mo;
    				}
    			}
    		}
    		f[x][st][0] = (g[0][0] + g[1][0]) % mo;
    		f[x][st][1] = (g[0][1] + g[1][1]) % mo;
    	}
    }
    
    int main() {
    	scanf("%d", &n);
    	fo(i, 1, n - 1) {
    		scanf("%d %d", &x, &y);
    		link(x, y); link(y, x);
    	}
    	dg(1);
    	pp("%lld
    ", f[1][1][1]);
    }
    
  • 相关阅读:
    NHibernate使用
    成为专业程序员路上用到的各种优秀资料、神器及框架
    SignalR
    sql 语句 事务
    entity framework 数据加载三种方式的异同(延迟加载,预加载,显示加载)
    获取前一个页面的地址
    给button按钮加回车事件
    单元测试
    教学资源网站整理
    Go资源
  • 原文地址:https://www.cnblogs.com/coldchair/p/12789866.html
Copyright © 2011-2022 走看看