• Interesting Vertices


    Interesting Vertices(前向星+思维+dfs回溯)

    参考博客:https://blog.csdn.net/I_believe_CWJ/article/details/102472012

    题目大意:给你一课有n个节点的树,其中有k个节点被染色,求有多少个节点满足自身没有被染色
    并且它的每棵子树中都至少有一个节点被染色。
    解题思路:dfs回溯类似求树的重心的方式求解,dfsdfs回溯可以得到每个节点的它的子树中是否都有染色的点
    并统计所有子树中染色点的个数sum,然后走向父亲的那棵子树中被染色的点数就为k−sum,
    这样即可判断此节点是否满足条件。

    AC_Code

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <ctime>
     5 #include <cmath>
     6 #include <vector>
     7 #include <map>
     8 #include <vector>
     9 #include <algorithm>
    10 #define bug printf("*********
    ");
    11 #define mem0(a) memset(a, 0, sizeof(a));
    12 #define mem1(a) memset(a, -1, sizeof(a));
    13 #define ios ios::sync_with_stdio(false);
    14 #define pb(x) push_back(x)
    15 using namespace std;
    16 typedef long long LL;
    17 const LL mod = 1e9 + 7;
    18 const int inf = 1e9 + 7;
    19 const LL INF = 1e18 + 7;
    20 const double eps = acos(-1.0);
    21 
    22 int n, k, cnt;
    23 int c[200010];///标记是否是染色点
    24 int head[200010];///前向星使用
    25 int vis[200010];///标记是否访问过
    26 int sz[200010];///sz[i]表示第i个节点的子树中一共有多少个被染色
    27 
    28 struct edge {
    29     int to, nxt;
    30 }e[200010*2];
    31 
    32 void add(int u, int v) {
    33     e[cnt].to = v;
    34     e[cnt].nxt = head[u];
    35     head[u] = cnt ++;
    36 }
    37 
    38 vector<int> ans;
    39 
    40 void dfs(int u) {
    41     vis[u] = 1;
    42     sz[u] = c[u];
    43     int flag = 1;
    44     for(int i = head[u]; ~i; i = e[i].nxt) {
    45         int en = e[i].to;
    46         if(vis[en]) continue;
    47         dfs(en);
    48         if(!sz[en]) flag = 0;///此子树没有被染色
    49         sz[u] += sz[en];
    50     }
    51     ///k-sz[u]>0 是指u的父亲节点所带领的那棵子树有被染色
    52     ///!c[u]是指满足改点没有被染色
    53     ///flag表示点的所有子树都有被染色
    54     ///u==1是因为1节点没有父亲节点了
    55     if(!c[u] && flag && (k-sz[u]>0 || u == 1)) ans.pb(u);
    56 }
    57 
    58 int main() {
    59     int x, y;
    60     while(~scanf("%d%d", &n, &k)) {
    61         mem0(vis);mem0(c);mem1(head);
    62         cnt = 0;
    63         ans.clear();
    64         for(int i = 0; i < k; i ++) {
    65             scanf("%d", &x);
    66             c[x] = 1;
    67         }
    68         for(int i = 0; i < n-1; i ++) {
    69             scanf("%d%d", &x, &y);
    70             add(x, y), add(y, x);
    71         }
    72         dfs(1);///假装以1为树的总根
    73         sort(ans.begin(), ans.end());
    74         printf("%d
    ", ans.size());
    75         for(auto i : ans) {
    76             printf("%d ", i);
    77         }
    78         printf("
    ");
    79     }
    80     return 0;
    81 }
  • 相关阅读:
    设计模式走一遍---观察者模式
    从0打卡leetcode之day 6--最长回文串
    回车与换行的故事
    线程安全(中)--彻底搞懂synchronized(从偏向锁到重量级锁)
    线程安全(上)--彻底搞懂volatile关键字
    从0打卡leetcode之day 5 ---两个排序数组的中位数
    聊一聊让我蒙蔽一晚上的各种常量池
    从零打卡leetcode之day 4--无重复最长字符串
    C4.5算法总结
    数据库游标使用
  • 原文地址:https://www.cnblogs.com/wsy107316/p/11700538.html
Copyright © 2020-2023  润新知