51nod 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.二分,二分枚举最多能挂到第k个绳子,从第k个往第一个推,若发现当前可以绳子可以承载下所有重物则将k增大,否则将k减小。
2.并查集,并查集自底向上维护每一个绳子,若当前绳子挂的负重大于承重则从最后一个重物开始往前删,直到负重小于承重,这样下去等挂到根节点的时候所有的重物都已经挂完了,剩下没有删掉的个数即为最多的个数
二分:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 5 using namespace std; 6 typedef long long LL; 7 const int maxn = 50005; 8 struct node { 9 LL w, c, pre, cost; 10 }e[maxn]; 11 LL n; 12 void reset() 13 { 14 for (int i = 0; i <= n; i++) 15 e[i].cost = 0; 16 } 17 int main() 18 { 19 ios::sync_with_stdio(false); 20 while (cin >> n) { 21 for (int i = 1; i <= n; i++) { 22 cin >> e[i].c >> e[i].w >> e[i].pre; 23 e[i].pre++; 24 } 25 int l = 1, r = n; bool flag; 26 while (l <= r) { 27 int mid = (l + r) >> 1; 28 flag = true; 29 reset(); 30 for (int i = mid; i >= 1; i--) { 31 e[i].cost += e[i].w; 32 if (e[i].cost > e[i].c) { 33 flag = false; break; 34 } 35 e[e[i].pre].cost += e[i].cost; 36 } 37 if (flag) l = mid + 1; 38 else r = mid - 1; 39 } 40 cout << r << endl; 41 } 42 return 0; 43 }
并查集:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 5 using namespace std; 6 const int maxn = 50005; 7 typedef long long LL; 8 struct Task { 9 int w, c, pre, cost; 10 }e[maxn]; 11 int n, f[maxn]; 12 int Find(int x) 13 { 14 if (f[x] != x) 15 f[x] = Find(f[x]); 16 return f[x]; 17 } 18 int main() 19 { 20 ios::sync_with_stdio(false); 21 while (cin >> n) { 22 for (int i = 1; i <= n; i++) { 23 cin >> e[i].c >> e[i].w >> e[i].pre; 24 e[i].cost += e[i].w; e[i].pre++; 25 f[i] = i; 26 } 27 int ans = n; 28 for (int i = n; i >= 1; i--) { 29 while (e[i].cost > e[i].c) { 30 int tmp = Find(ans); 31 e[tmp].cost -= e[ans].w; 32 ans--; 33 } 34 e[e[i].pre].cost += e[i].cost; 35 f[i] = e[i].pre; 36 } 37 cout << ans << endl; 38 } 39 return 0; 40 }