11.02T3 贪心
1.能量获取3764
(power.cpp/c/pas)
【问题描述】
封印台是一个树形的结构,魂珠放置的位置就是根节点(编号为 0)。还有 n 个其它节点(编号 1~n)上放置着封印石,编号为i的封印石需要从魂珠上获取 Ei 的能量。能量只能沿着树边从魂珠传向封印石,每条边有一个能够传递的能量上限 Wi,魂珠的能量是无穷大的。作为封印开始前的准备工作,请你求出最多能满足多少颗封印石的能量需求?
注意:能量可以经过一个节点,不满足它的需求而传向下一个节点。每条边仅能传递一次能量。
【输入】
第一行一个整数n,表示除根节点之外其它节点的数量。
接下来 n 行,第 i+1 行有三个整数 Fi、Ei、Wi,分别表示 i 号节点的父节点、i 号节点上封印石的能量需求、连接节点 i与Fi的边最多能传递多少能量。
【输出】
最多能满足多少颗封印石的能量需求。
【输入样例】
4
0 3 2
0 100 100
1 1 1
2 75 80
【输出样例】
2
【数据范围与约定】
对于100%的数据,满足1<=n<=1000,0<=Fi<=n,0<=Ei,Wi<=100。
【分析】贪心
每次选取能量需求最小的节点,扫描它到根节点的路径上的边的容量,看能否满足,如果能满足就把它到根节点的路径上的边的容量都减去它的需求即可。
本题如果把握不好贪心的正确性也可以写树状动规(多叉树,背包转移),但是显然编程复杂度就上升了一个层次。
少见的贪心,其实树上背包也挺简单的
code:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #define N 100006 5 using namespace std; 6 struct node{ 7 int id,w; 8 }p[N]; 9 int fa[N],w[N],E[N]; 10 bool cmp(const node&a,const node&b){ 11 return a.w<b.w; 12 } 13 int main(){ 14 int n;cin>>n; 15 for(int i=1;i<=n;i++){ 16 cin>>fa[i]>>p[i].w>>w[i]; 17 p[i].id=i; 18 } 19 sort(p+1,p+n+1,cmp); 20 int ans=0; 21 for(int i=1;i<=n;i++){ 22 int min0=99999999; 23 int temp=p[i].id; 24 while(temp){ 25 min0=min(min0,w[temp]); 26 temp=fa[temp]; 27 // cout<<temp<<"<-temp"; 28 } 29 // cout<<'\n'; 30 // cout<<p[i].id<<" "<<min0<<'\n'; 31 if(min0>=p[i].w){ 32 ans++; 33 temp=p[i].id; 34 while(temp){ 35 w[temp]-=p[i].w; 36 temp=fa[temp]; 37 } 38 } 39 } 40 cout<<ans; 41 return 0; 42 }
over