2 条题解

  • 0
    @ 2026-9-23 0:12:29

    这道题就是一个暴搜题。

    首先我们读入这棵树,将所有边连上。

    然后我们从节点 11 开始 DFS,我们要定义如下数组:

    • minx[u]minx[u] 表示以 uu 为根的子树中的最小权值(初始值为 c[u]c[u])
    • cnt[u]cnt[u] 表示以 uu 为根的子树中挂了多少礼物
    • ans[u]ans[u] 表示以 uu 为根装饰的最小费用

    先遍历一边树,将上面的信息全都求出来。

    然后如果我们现在的 cnt[u]cnt[u] 已经超过或等于 d[u]d[u] 了,说明已经符合要求,直接返回即可;

    否则就需要再补全剩余的部分,也就是权值 ×\times 需要补全的礼物数。

    最后别忘了把 cnt[u]cnt[u] 的数量换掉。

    注意 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
      @ 2025-10-8 17:00:32
      #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

      【递归+贪心】树上装饰[USACO11MAR] Tree Decoration G

      信息

      ID
      2281
      时间
      1000ms
      内存
      128MiB
      难度
      5
      标签
      递交数
      36
      已通过
      16
      上传者