51 Nod 1307 绳子与重物

                       1307 绳子与重物
有N条绳子编号 0 至 N - 1,每条绳子后面栓了一个重物重量为Wi,绳子的最大负重为Ci。每条绳子或挂在别的绳子下或直接挂在钩子上(编号-1)。如果绳子下所有重物的重量大于绳子的最大负重就会断掉(等于不会断)。依次给出每条绳子的负重Ci、重物的重量Wi以及绳子会挂在之前的哪条绳子的下面,问最多挂多少个绳子而不会出现绳子断掉的情况。
 
例如下图:
 
5, 2, -1
3, 3, 0
6, 1, -1
3, 1, 0
3, 2, 3
 
 
 
挂到第4个时会有绳子断掉,所以输出3。
 
 
Input
第1行:1个数N,表示绳子的数量(1 <= N <= 50000)。
第2 - N + 1行:每行3个数,Ci, Wi, Pi,Ci表示最大负重,Wi表示重物的重量,Pi表示挂在哪个绳子上,如果直接挂在钩子上则Pi = -1(1 <= Ci <= 10^9,1 <= Wi <= 10^9,-1 <= Pi <= N - 2)。
Output
输出1个数,最多挂到第几个绳子,不会出现绳子断掉的情况。
Input示例
5
5 2 -1
3 3 0
6 1 -1
3 1 0
3 2 3
Output示例
3

思路: 并查集 每次向上更新 当前绳子的负重 如果超出限制 就退出
 
 1 #include <cstdio>
 2 #include <cctype>
 3 
 4 typedef long long LL;
 5 
 6 const int MAXN=50010;
 7 
 8 int n;
 9 
10 bool flag;
11 
12 int w[MAXN],c[MAXN],f[MAXN];
13 
14 LL d[MAXN];
15 
16 inline void read(int&x) {
17     int f=1;register char c=getchar();
18     for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());
19     for(;isdigit(c);x=x*10+c-48,c=getchar());
20     x=x*f;
21 }
22 
23 bool find(int p,int v) {
24     if(p==-1) return true;
25     if(d[p]+v>c[p]) return false;
26     d[p]+=v;
27     if(find(f[p],v)) return true;
28     return false;
29 }
30 
31 int hh() {
32     read(n);
33     
34     for(int fa,i=0; i<n; ++i) {
35         read(c[i]);read(w[i]);read(fa);
36         f[i]=fa;
37         if(!find(i,w[i])) {
38             flag=true;
39             printf("%d\n",i);
40             break;
41         }
42     }
43     if(!flag) printf("%d\n",n);
44     
45     return 0;
46 }
47 
48 int sb=hh();
49 int main(int argc,char**argv) {;}
代码

 

 
posted @ 2017-10-25 20:08  拿叉插猹哈  阅读(159)  评论(0编辑  收藏  举报