• 最大独立集 ccpcwannnafly (贪心最大独立集)


    题目描述

     

    树上最大独立集是个非常简单的问题,可怜想让它变得稍微难一点。

    可怜最开始有一棵 nn 个点无根树 TT,令 T(i)T(i) 为将点 ii 作为根后得到的有根树。

    可怜用 mm 次操作构造了 m+1m+1 棵树 T'_0T0 至 T'_mTm,其中 T'_0 = T(1)T0=T(1)。第 ii 次操作,可怜选择了一个节点 k_iki,它用如下的方式构造了 T'_iTi

    • 新建一棵和 T(k_i)T(ki) 一样的有根树 T_bTb
    • 新建 nn 棵和 T'_{i-1}Ti1 一样的有根树,并将第 jj 棵树的根节点的父亲设置为 T_bTb 中第 jj 个点,即加上一条连接它们的边。
    • 这样就得到了一个点数为  ext{size}(T(k_i)) + n imes ext{size}(T'_{i-1})size(T(ki))+n×size(Ti1) 的树 T_iTi,它的根节点是 T_bTb 中的节点 k_iki

    现在可怜希望你对 T_0T0 至 T_mTm,分别求出这 m+1m+1 棵树的最大独立集大小。

    有根树 TT 的独立集 SS 的定义是 :SS 是 TT 上节点的子集,同时对于任意 SS 中的点 ii,ii 的父亲 f_ifi 不在 SS 中。

     

     
     

    输入描述

     

    第一行输入两个整数 n,m(1 leq n,m leq 10^5)n,m(1n,m105),表示无根树上的节点个数与可怜进行的操作次数。

    接下来 n-1n1 行每行两个整数 u,v(1 leq u,v leq n)u,v(1u,vn) 表示书上的一条边。

    接下来 mm 行每行一个整数 k_i(1 leq k_i leq n)ki(1kin) 表示在第 ii 次操作中,可怜选择的节点。

     

    输出描述

     

    输出 m+1m+1 行,每行一个整数,表示对应的树的最大独立集的大小。答案可能很大, 对 998244353998244353 取模后输出。

     

    样例输入 1 

    1 5
    1
    1
    1
    1
    1

    样例输出 1

    1
    1
    2
    2
    3
    3

    样例输入 2 

    5 5
    1 2
    2 3
    2 4
    1 5
    5
    4
    3
    2
    1

    样例输出 2

    3
    18
    93
    465
    2328
    11643






    基础是要会求树上独立集,一个是树形dp,太暴力了,并且这里的也用不上。
    然年就是有一个贪心的做法,
    就是每次取树的叶子, 删掉叶子的fa,一次类推
    实现的话,一次dfs就行了。
    然后

    树上独立集的贪心做法:

    每次取出叶子节点加入答案,然后将其父节点扔掉,循环操作,直至没有节点

    那么考虑这一道题的操作,对于一棵树T(ki)来说T(ki)来说
    它的每一个节点下面都连着一棵独立的树

    那么这些独立的树都可以分别贪心求最大独立集

    再考虑这些独立的树做完之后剩下的T(ki)T(ki)
    如果这些独立的树的最大独立集需要取到其根节点,那么T(ki)中所有节点都不能取T(ki)中所有节点都不能取
    否则T(ki)的贡献就是以ki为根的最大独立集T(ki)的贡献就是以ki为根的最大独立集
    这时候需要预处理出以x∈[1,n]为根的最大独立集中是否需要用到xx∈[1,n]为根的最大独立集中是否需要用到x
    树形dp

    第一次dp ,f[i]表示只考虑i的子树当前点取不取f[i]表示只考虑i的子树当前点取不取
    显然,对于所有叶子节点都是取的 ,f[i]=1f[i]=1
    那么对于非叶子节点 f[i]=1当且仅当其所有儿子的f[i]=0f[i]=1当且仅当其所有儿子的f[i]=0

    第二次dp g[i]表示不考虑i的子树当前点取不取g[i]表示不考虑i的子树当前点取不取
    显然,g[1]=1表示根节点不考虑其子树是取的g[1]=1表示根节点不考虑其子树是取的
    再考虑其他点u,如果u是不取的,当且仅当g[fa[u]]=1并且其父亲除它u,如果u是不取的,当且仅当g[fa[u]]=1并且其父亲除它
    以外的儿子中的f[i]都是不取的

    第二次dp g[i]ig[i]表示不考虑i的子树当前点取不取

    显然,g[1]=1g[1]=1表示根节点不考虑其子树是取的

    再考虑其他点uug[fa[u]]=1u,如果u是不取的,当且仅当g[fa[u]]=1并且其父亲除它

    f[i]






     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define N 200010
     6 const ll MOD = (ll)998244353;
     7 int n, m; ll base; 
     8 vector <int> G[N]; 
     9 
    10 int fa[N], cnt[N], need[N];
    11 // 0 get > 0 not get  for cnt
    12 void DFS(int u)
    13 {
    14     cnt[u] = 0;
    15     for (auto v : G[u]) if (v != fa[u])
    16     {
    17         fa[v] = u;
    18         DFS(v); 
    19         if (cnt[v] == 0) ++cnt[u];  
    20     }
    21     if (cnt[u] == 0) ++base;
    22 }
    23 
    24 
    25 // need 0 get 1 not get 
    26 void DFS2(int u)
    27 {
    28     if (u != 1)
    29     {
    30         if (need[fa[u]] == 0 && cnt[fa[u]] - (cnt[u] == 0) == 0) need[u] = 1;
    31         else need[u] = 0;
    32     }
    33     for (auto v : G[u]) if (v != fa[u])
    34         DFS2(v); 
    35 }
    36 
    37 int main()
    38 {
    39     while (scanf("%d%d", &n, &m) != EOF)
    40     {
    41         base = 0;
    42         for (int i = 1; i <= n; ++i) G[i].clear();
    43         for (int i = 1, u, v; i < n; ++i)
    44         {
    45             scanf("%d%d", &u, &v);
    46             G[u].push_back(v);
    47             G[v].push_back(u);
    48         }
    49         DFS(1); 
    50         need[1] = 0;
    51         DFS2(1);
    52         for (int i = 1; i <= n; ++i) 
    53         {
    54             if (cnt[i] == 0 && need[i] == 0) need[i] = 1;
    55             else need[i] = 0;
    56         }
    57         ll res = base;        
    58         int vis = need[1];  
    59         for (int i = 1, x; i <= m; ++i)
    60         {
    61             scanf("%d", &x);
    62             printf("%lld
    ", res);
    63             res = (res * n) % MOD; 
    64             if (vis == 0) res = (res + base) % MOD, vis = need[x]; 
    65             else vis = 0;  
    66         }        
    67         printf("%lld
    ", res);
    68     }
    69     return 0;
    70 }














  • 相关阅读:
    UNITY 多个子MESH与贴图的对应关系
    UNITY 优化之带Animator的Go.SetActive耗时问题,在手机上,这个问题似乎并不存在,因为优化了后手机上运行帧率并未明显提升
    发现一个好办法-有问题可以到UNITY论坛搜索
    静态函数造成GC的原因
    关于GC.Collect在不同机器上表现不一致问题
    VULKAN学习资料收集
    Array.Resize(ref arry, size);
    玩游戏消耗精力
    浮点数与定点数问题
    P8 Visible Lattice Points
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/10956857.html
Copyright © 2020-2023  润新知