2 条题解
-
0
这道题就是一个暴搜题。
首先我们读入这棵树,将所有边连上。
然后我们从节点 开始 DFS,我们要定义如下数组:
- 表示以 为根的子树中的最小权值(初始值为 )
- 表示以 为根的子树中挂了多少礼物
- 表示以 为根装饰的最小费用
先遍历一边树,将上面的信息全都求出来。
然后如果我们现在的 已经超过或等于 了,说明已经符合要求,直接返回即可;
否则就需要再补全剩余的部分,也就是权值 需要补全的礼物数。
最后别忘了把 的数量换掉。
注意 long long。
Code:
#include <bits/stdc++.h> #define int long long using namespace std; const int N = 1e5 + 10, M = N * 2; int n; int d[N], c[N]; int h[N], e[M], ne[M], idx; int minx[N]; int cnt[N]; int ans[N]; void add(int a, int b) { e[idx] = b, ne[idx] = h[a], h[a] = idx++; } void dfs(int u, int fa) { minx[u] = c[u]; for (int i = h[u]; ~i; i = ne[i]) { int j = e[i]; if (j == fa) continue; dfs(j, u); cnt[u] += cnt[j]; minx[u] = min(minx[u], minx[j]); ans[u] += ans[j]; } if (cnt[u] >= d[u]) return; ans[u] += minx[u] * (d[u] - cnt[u]); cnt[u] = d[u]; } signed main() { ios::sync_with_stdio(0); cin.tie(0); memset(h, -1, sizeof h); memset(minx, 0x3f, sizeof minx); cin >> n; for (int i = 1; i <= n; i++) { int x; cin >> x >> d[i] >> c[i]; if (x == -1) continue; else add(x, i), add(i, x); } dfs(1, -1); cout << ans[1] << '\n'; return 0; } -
0
#include<bits/stdc++.h> using namespace std; typedef long long LL; const int N = 1e5+10; vector<int> G[N]; LL t[N], c[N], tt[N], ans; bool vis[N]; void dfs(int x) { vis[x] = 1; for(int y: G[x])if(!vis[y]){ dfs(y); c[x] = min(c[x] , c[y]); tt[x] += tt[y]; } if(tt[x] < t[x]) { ans += (t[x]-tt[x]) * c[x]; tt[x] = t[x]; } } int main() { int n,rt;scanf("%d",&n); for(int i = 1,x; i <= n; i++) { scanf("%d%lld%lld",&x,&t[i],&c[i]); if(x != -1) G[x].push_back(i); else rt = i; } ans=0; memset(vis,0,sizeof(vis)); dfs(rt); printf("%lld\n",ans); return 0; }
- 1
信息
- ID
- 2281
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 5
- 标签
- 递交数
- 36
- 已通过
- 16
- 上传者