CF1394D 题解
CF1394D Boboniu and Jianghu 题解
Links
Solution
可以处理出对于每个点,向下
对于个端点指出的边,若两端点的
利用 dfs 进行转移即可。
该部分代码:
void dfs(int u, int fa) { int sum = 0, cnt_up = 0, cnt_down = 0; for (int i = head[u]; i; i = edge[i].nxt) { int v = edge[i].to; if (v == fa) { continue; } dfs(v, u); // 可以递增,可以递减 if (points[u].b == points[v].b) { // 换一个的价值 st[u].push_back(dp[v][1] - dp[v][0]); // 先假定递增 ++cnt_up; sum += dp[v][0]; } else if (points[u].b > points[v].b) { ++cnt_up; sum += dp[v][0]; } else { ++cnt_down; sum += dp[v][1]; } } sort(st[u].begin(), st[u].end()); // 把多少个转换 for (int i = 0; i <= st[u].size(); i++) { dp[u][0] = min(dp[u][0], sum + max(cnt_up, cnt_down + (u != 1)) * points[u].a); dp[u][1] = min(dp[u][1], sum + max(cnt_up + (u != 1), cnt_down) * points[u].a); --cnt_up, ++cnt_down; // 改变了一条边 if (i < st[u].size()) { sum += st[u][i]; } } }
注意到当
Codes
#include <bits/stdc++.h> using namespace std; #define int long long #define max_n 210101 void read(int &p) { p = 0; int k = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') { k = -1; } c = getchar(); } while (c >= '0' && c <= '9') { p = p * 10 + c - '0'; c = getchar(); } p *= k; return; } void write_(int x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) { write_(x / 10); } putchar(x % 10 + '0'); } void writesp(int x) { write_(x); putchar(' '); } void writeln(int x) { write_(x); putchar('\n'); } int n; struct node { int to, nxt; } edge[max_n << 1]; int head[max_n], tot; void add(int u, int v) { edge[++tot].to = v; edge[tot].nxt = head[u]; head[u] = tot; } struct Point { int a, b; } points[max_n]; int dp[max_n][2]; vector<int> st[max_n]; void dfs(int u, int fa) { int sum = 0, cnt_up = 0, cnt_down = 0; for (int i = head[u]; i; i = edge[i].nxt) { int v = edge[i].to; if (v == fa) { continue; } dfs(v, u); // 可以递增,可以递减 if (points[u].b == points[v].b) { // 换一个的价值 st[u].push_back(dp[v][1] - dp[v][0]); // 先假定递增 ++cnt_up; sum += dp[v][0]; } else if (points[u].b > points[v].b) { ++cnt_up; sum += dp[v][0]; } else { ++cnt_down; sum += dp[v][1]; } } sort(st[u].begin(), st[u].end()); // 把多少个转换 for (int i = 0; i <= st[u].size(); i++) { dp[u][0] = min(dp[u][0], sum + max(cnt_up, cnt_down + (u != 1)) * points[u].a); dp[u][1] = min(dp[u][1], sum + max(cnt_up + (u != 1), cnt_down) * points[u].a); --cnt_up, ++cnt_down; // 改变了一条边 if (i < st[u].size()) { sum += st[u][i]; } } } signed main() { #if _clang_ freopen("1.in", "r", stdin); freopen("1.out", "w", stdout); #endif read(n); for (int i = 1; i <= n; i++) { read(points[i].a); } for (int i = 1; i <= n; i++) { read(points[i].b); } for (int i = 1, u, v; i < n; i++) { read(u), read(v); add(u, v); add(v, u); } memset(dp, 0x3f, sizeof(dp)); dfs(1, 0); writeln(min(dp[1][0], dp[1][1])); return 0; }
本文来自博客园,作者:cn_ryh,转载请注明原文链接:https://www.cnblogs.com/yuhang-ren/p/17523698.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步