【问题描述】

有n个炸弹,有些炸弹牵了一根单向引线(也就是说引线只有在这一端能被炸弹点燃),只要引爆了这个炸弹,用引线连接的下一个炸弹也会爆炸。每个炸弹还有个得分,当这个炸弹被引爆后就能得到相应得分。

现在要你引爆k个炸弹,使得分最大。

【输入格式】

第1行两个整数n、k。

接下来n行每行两个整数a[i]、b[i]。a[i]表示这个炸弹用引线连接的下一个炸弹,如果a[i]为0,则表示这个炸弹没连接引线。b[i]表示这个炸弹的得分。

【输出格式】

  仅一个数,表示最大得分

【输入样例】bomb.in

8 2

0 1

1 1

2 100

2 100

0 1

5 1

6 2

6 2

【输出样例】bomb.out

202

【数据规模】

1≤b[i]≤1000000

对于30%的数据,n≤1000    k≤30

对于60%的数据,n≤50000    k≤100

对于100%的数据,n≤200000    k≤500

/*
  将每个点能引爆的最大价值求出
  贪心
*/
#include<cstdio>
#include<cstring>
#include<fstream>
#define maxn 200010
using namespace std;
ifstream cin("bomp.in");
ofstream cout("bomp.out");
int n,k,o,i;
long long ans;
int x[maxn];
int value[maxn],num[maxn];
long long sum[maxn];
bool v[maxn];

void quicksort(int l,int r)
{
	int i,j,z;
	long long x,y;
	i=l;j=r;
	x=sum[(l+r)/2];
	do
	{
		while (sum[i]>x) i++;
		while (sum[j]<x) j--;
		if (i<=j)
		{
			y=sum[i];
			sum[i]=sum[j];
			sum[j]=y;
			z=num[i];
			num[i]=num[j];
			num[j]=z;
			i++;j--;
		}
	}while (i<j);
	if (i<r) quicksort(i,r);
	if (l<j) quicksort(l,j);
}

int main()
{
	//freopen("bomp.in","r",stdin);
	//freopen("bomp.out","w",stdout);
	//scanf("%d%d",&n,&k);
	cin>>n>>k;
	for (i=1;i<=n;i++)
	{
		//scanf("%d%d",&x[i],&value[i]);
		cin>>x[i]>>value[i];
	}
    for (i=1;i<=n;i++)
	{
		int t;
		t=x[i];
		sum[i]=value[i];
		while (t)
		{
			sum[i]+=value[t];
			t=x[t];
		}
	}
    for (i=1;i<=n;i++) num[i]=i;
	quicksort(1,n);
	memset(v,0,sizeof(v));
	for (i=1;i<=n;i++)
	{
		int t=x[num[i]];
		v[num[i]]=1;
		while (t)
		{
			if (v[t]) 
				sum[i]-=value[t];
			v[t]=1;
			t=x[t];
		}
	}
    quicksort(1,n);
	ans=0;
	for (i=1;i<=k;i++) ans+=sum[i];
	cout<<ans<<endl;
	//printf("%lld\n",ans);
	return 0;
}