zoukankan      html  css  js  c++  java
  • 【YBTOJ】【树形dp】块的计数

    题意

    给定一棵 (n) 个节点的树,每个点有个喜欢程度。求 选联通块,并且这个联通块包含最大的点权的方案数。

    分析

    很难想的一道题……
    原本思路:将权值最大的点设为根,跑一遍树形dp即可。
    但是考虑到,权值最大的点可能不止一个,于是此做法失效。


    考虑设(dp_u)表示在(u)的子树内,必定选取点(u)作为联通块,且包含最大点权的联通块个数。
    使用树形dp,发现难以从子树中转移(因为最大点权的点可能不止一个)
    于是考虑:使用补集转化思想,反向处理。
    f[u]表示以(u)的子树内所有联通块个数(必定选取(u)),(g[u])(u)的子树内不包含最大点权的联通块个数(必定选取(v))。
    则有:

    [f_u = prod_{vin son_u}(f_v+1) ]

    (对于每棵树,选取其子树(v)(f_v)种,不选有(1)种)
    同理,有:

    [g_u=left{egin{matrix} prod_{vin son_u} (g_v+1) , val_v eq max\ 0 , val_v = max end{matrix} ight. ]

    则答案为:(sum (f_u-g_u)).

    代码

    #include <bits/stdc++.h>
    #define fo(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    const int INF = 0x3f3f3f3f,N = 1e5+5,mod = 998244353;
    typedef long long ll;
    typedef unsigned long long ull;
    inline ll read(){
    	ll ret=0;char ch=' ',c=getchar();
    	while(!(c>='0'&&c<='9'))ch=c,c=getchar();
    	while(c>='0'&&c<='9')ret=(ret<<1)+(ret<<3)+c-'0',c=getchar();
    	return ch=='-'?-ret:ret;
    }
    int n,m;
    struct Edge{int to,nxt;}e[N<<1];
    int head[N],ecnt = -1;
    inline void add_edge(int u,int v){e[++ecnt] = (Edge){v,head[u]};head[u] = ecnt;}
    
    ll a[N],mx=-1ll*INF*INF;
    ll f[N],g[N];
    ll ans;
    void dfs(int u,int _f){
    	f[u] = 1 , g[u] = a[u] != mx;
    	for(int i = head[u] ; ~i ; i = e[i].nxt){
    		int v = e[i].to;
    		if(v == _f)continue;
    		dfs(v,u);
    		(f[u] *= f[v]+1) %= mod,
    		(g[u] *= g[v]+1) %= mod;
    	} 
    	(ans += f[u]-g[u]+mod) %= mod; 
    }
    signed main(){
    	memset(head,-1,sizeof(head));
    	n = read();
    	for(int i = 1 ; i <= n ; i ++)
    		a[i] = read(),
    		mx = max(a[i],mx);
    	for(int i = 1 ; i < n ; i ++){
    		int u = read() , v = read();
    		add_edge(u,v);add_edge(v,u);
    	}
    	dfs(1,0);
    	printf("%lld",ans);
    }
    
    
  • 相关阅读:
    Qt5.3.0 for android windows平台下搭建及demo(虫子的博客)
    不分享,用户很少,什么都没有,没有秒传
    Entity Framework 5.0系列之约定配置
    学习SQL关联查询
    SQL语句调优
    数组总结篇(上)
    实现同一套代码针对不同平台工程的编辑和编译
    dispatch队列
    SOCKET网络编程快速上手(一)
    Javascript判断两个日期是否相等
  • 原文地址:https://www.cnblogs.com/Shinomiya/p/15257333.html
Copyright © 2011-2022 走看看