练习 3C Tree

C. Infected Tree

Problem - C - Codeforces

问题描述:一个二叉树,根节点被感染了,可以通过删除一个节点使这个树分成两个部分,从而使分离开的子树无法被感染,求这样操作,有最多多少个节点是未被感染的(删除的节点不算未被感染的)。

思路:树形dp。f[u]表示为u被感染后他的子树有最多多少个的节点未被感染。如果u是叶子节点,那么就是0;如果u只要一个节点,那么就是siz[v] - 1;如果有两个节点,那么就是max(siz[v1] - 1 + f[v2], siz[v2] - 1 + f[v1])
F ( u ) = { 叶子节点 0 一个子节点 s i z v − 1 两个子节点 m a x ( s i z v 1 − 1 + f v 2 , s i z v 2 − 1 + f v 1 ) F(u) = \begin{cases} 叶子节点 \quad 0 \\ 一个子节点 \quad sizv - 1 \\ 两个子节点 \quad max(sizv1- 1 + fv2, sizv2 - 1 + fv1) \end{cases} F(u)=⎩ ⎨ ⎧叶子节点0一个子节点sizv−1两个子节点max(sizv1−1+fv2,sizv2−1+fv1)

边界:无。

目标:
F ( 1 ) F(1) F(1)

注意事项:u的子节点不是g[u].size(),由于建树是双向边,因此多一个<u, fu>这条边。而且,也不能单纯直接令v1 = g[u][0], v2 = g[u][1],原因同上。但是可以用两个变量去处理v1 v2

代码:

cpp 复制代码
void solve() {
    int n; cin>>n;
    vector<vector<int>> g(n + 1);
    for(int i = 1; i < n; ++i) {
        int u,v; cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    vector<int> f(n + 1), siz(n + 1);
    auto dfs = [&](auto &&dfs, int u, int fu) -> void {
        siz[u] = 1;
        int cnt = 0;
        PII son = {-1,-1};
        for(auto y: g[u]) {
            if(y == fu) continue;
            dfs(dfs, y,u);
            cnt++;
            if(son.vf == -1) son.vf = y;
            else son.vs = y;
            siz[u] += siz[y];
        }
        if(cnt == 0) {
            f[u] = 0;
        }
        if(cnt == 1) {
            f[u] = siz[ son.vf] - 1;
        }
        if(cnt == 2) {
            int v1 = son.vf, v2 = son.vs;
            f[u] = max(siz[v1] - 1 + f[v2], siz[v2] - 1 + f[v1]);
        }
    };
    dfs(dfs,1,-1);
    cout<<f[1]<<endl;
}

C. Kefa and Park

Problem - C - Codeforces

问题描述:一个树,叶子节点有餐馆,从根节点出发到餐馆求有多少条路。限制条件是在一条路中,不能走连续k个点权为1的点。

思路:记录一条路径上连续的1的个数,如果连续的1的个数大于k,则后面怎么都到达不了,否则就有可能。之后叶子节点能否到达即可。

代码:

cpp 复制代码
void solve() {
    int n,k; cin>>n>>k;
    vector<int> vw(n + 1),lnow(n + 1), leaf(n + 1);
    vector<vector<int>> g(n + 1);
    for(int i = 1; i <= n; ++i) cin>>vw[i];
    for(int i = 1; i < n; ++i) {
        int u,v; cin>>u>>v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    auto dfs = [&] (auto &&dfs, int u, int fu) -> void {
        for(auto y: g[u]) {
            if(y == fu) continue;
            if(vw[y] == 0) {
                lnow[y] = 0;
            } else {
                lnow[y] = lnow[u] + 1;
            }
            if(lnow[y] > k) continue;
            dfs(dfs, y,u);
        }
        if(g[u].size() == 1) leaf[u] = 1;
    };
    // 对根节点连续1进行处理
    lnow[1] = vw[1];
    dfs(dfs,1,-1);
    int ans = 0;
    for(int i = 2; i <= n; ++i) if(leaf[i]) ans += 1;
    cout<<ans;
}

C. k-Tree

Problem - C - Codeforces

问题描述:一个满k叉树,对于一个节点来说,它到它k个节点的边权分为1...k。求从根节点出发,到路径和为n且存在一条大于等于d的边权的个数。

思路:像是数字三角形的那个dp,数据范围很小。而且只有一个特殊状态,是否大于d了。设状态为从根节点到一个节点的路径和为i时,存在了大于d的边和不存在大于d的边。

状态转移方程:
F ( i , j ) = { w < d F ( i , 0 ) + = F ( i − w , 0 ) ; F ( i , 1 ) + = F ( i − w , 1 ) w ≥ d F ( i , 1 ) + = F ( i − w , 1 ) + F ( i − w , 0 ) w 为 < u , v > 的边权 F(i,j) = \begin{cases} w < d \quad F(i,0) += F(i - w,0); \quad F(i,1) += F(i - w,1) \\ w \ge d \quad F(i,1) += F(i-w,1) + F(i-w,0) \\ \end{cases} \\ w为<u,v>的边权 F(i,j)={w<dF(i,0)+=F(i−w,0);F(i,1)+=F(i−w,1)w≥dF(i,1)+=F(i−w,1)+F(i−w,0)w为<u,v>的边权

边界:
F ( 0 , 0 ) = 1 F(0,0) = 1 F(0,0)=1

目标:
F ( n , 1 ) F(n,1) F(n,1)

注意: 如果w > i那这个i - w就是负数,不合法,因此遍历的应该是min(w,i)

代码:

cpp 复制代码
const LL mod = 1000000007;
LL f[N][N];
void inpfile();
void solve() {
    int n,k,d; cin>>n>>k>>d;
    f[0][0] = 1;
    for(int i = 1; i <= n; ++i) {
        for(int j = 1; j <= min(i,k); ++j) {
            if(j < d) f[i][0] += f[i - j][0], f[i][1] += f[i-j][1];
            else f[i][1] += f[i-j][1] + f[i-j][0];
            f[i][0] %= mod;
            f[i][1] %= mod;
        }
    }
    cout<<f[n][1];
}
相关推荐
船厂电气自动化ai大模型2 小时前
AI大模型与数学·第57课 傅里叶全套工具链综合实战:串联级数/连续变换/DFT/FFT,图像、音频、扩散模型完整例题
数据结构·人工智能·深度学习·算法·机器学习
人工智能培训3 小时前
人工智能数据安全下的个人信息保护实践方案
大数据·人工智能·算法·生活
元启数宇3 小时前
幕墙AI设计算法逻辑:元启数宇如何智能分格
人工智能·算法
宵时待雨3 小时前
优选算法专题16:多源BFS
算法·宽度优先
重生之后端学习4 小时前
53. 最大子数组和[中等]✅
java·数据结构·算法·leetcode·职场和发展
INGNIGHT4 小时前
1908 · 布尔表达式求值(stack单调栈&dfs)
开发语言·c++·算法
lucas_AI4 小时前
把表格压成 64 个 token,长文档问答反而更准了:先找表,再看数
人工智能·深度学习·算法
Zzz 小生5 小时前
Lazy Theta*:把昂贵的视线检测留到“真正需要”时再做
人工智能·算法·贪心算法·推荐算法
l1258655 小时前
# LangGraph Deep Research Agent 全流程设计:多轮研究、人机协同与真实来源管理
数据库·人工智能·python·算法·自然语言处理·oracle·langchain
青少儿编程课堂6 小时前
图形化编程实战:智能交通灯调度台,一个作品讲透循环、条件与广播
c++·python·算法·bfs·信息学竞赛