题解:
因为每个点只有一条出边,所以实际上每个点开始的路径只有一条。因此可以采用倍增的思路,先预处理每个点走步之后的答案,之后对每个点只要用这些来凑出长度为k的路径就可以了。
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n;
int f[100010],w[100010],ff[100010][40];
long long k,rmq[2][100010][40];
int main()
{
int now;
long long kk,sum,ans1,ans2,x;
scanf("%d%I64d",&n,&k);
for(int i=1;i<=n;i++){scanf("%d",&f[i]);f[i]++;}
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
kk=1;for(int i=1;i<=n;i++){ff[i][0]=f[i];rmq[1][i][0]=rmq[0][i][0]=w[i];}
for(int i=1;kk<=k;i++)
{
for(int j=1;j<=n;j++)
{
ff[j][i]=ff[ff[j][i-1]][i-1];
rmq[0][j][i]=rmq[0][j][i-1]+rmq[0][ff[j][i-1]][i-1];
rmq[1][j][i]=min(rmq[1][j][i-1],rmq[1][ff[j][i-1]][i-1]);
}
kk<<=1;
}
for(int i=1;i<=n;i++)
{
kk=1;x=ans1=0;ans2=w[i];now=i;
while(kk<=k){kk<<=1;x++;}kk>>=1;x--;
ans1+=rmq[0][i][x];ans2=min(ans2,rmq[1][i][x]);sum=kk;now=ff[i][x];
while(sum<k)
{
while((k-sum<kk)){kk>>=1;x--;}
ans1+=rmq[0][now][x];ans2=min(ans2,rmq[1][now][x]);sum+=kk;
now=ff[now][x];
}
printf("%I64d %I64d\n",ans1,ans2);
}
return 0;
}