有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
先根据P[i] 建边.
然后枚举答案-.-然后dfs判断。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
int c[50100],w[50100],p[50100];
int m;
bool fafe;
vector<int> V[50100];
int dfs(int x)
{
if (!fafe) return 0;
int he=w[x];
for (int i=0;i<V[x].size();i++)
{
if (V[x][i]<m)
he+=dfs(V[x][i]);
}
if (he>c[x])
fafe=false;
return he;
}
bool pan()
{
fafe=true;
for (int i=0;i<m;i++)
{
if (p[i]==-1)
dfs(i);
if (!fafe) break;
}
return fafe;
}
int main()
{
int n;cin>>n;
for (int i=0;i<n;i++)
{
cin>>c[i]>>w[i]>>p[i];
if (p[i]!=-1)
V[p[i]].push_back(i);
}
int l=1,r=n,ans=0;
while (l<=r)
{
m=(l+r)>>1;
if (pan())
{
ans=m;
l=m+1;
}
else
r=m-1;
}
cout<<ans<<endl;
return 0;
}