显示代码纯文本
#pragma GCC optimize(2)
#include <cstdio>
#include <cstring>
typedef long long ll;
template <typename T>
T min(T x, T y) {
return x < y ? x : y;
}
const int MAXN = 1e5 + 10;
int n;
ll k;
int son[MAXN], fa[MAXN];
int w[MAXN];
void Work1() {
for (int i = 1; i <= n; ++i) {
int now = i, mini = 0x7fffffff;
ll sum = 0;
for (int j = 1; j <= k; ++j) {
sum += w[now];
mini = min(mini, w[now]);
now = son[now];
}
printf("%lld %d\n", sum, mini);
}
}
bool dealt[MAXN], vis[MAXN], vis2[MAXN];
int tolooptimes[MAXN], loopmin[MAXN], loopsize[MAXN], loopstart[MAXN], toloopmin[MAXN];
ll loopsum[MAXN], toloopsum[MAXN];
void CalcLoopLengthAndSum(int root, int tms, ll sum, int k) {
vis2[root] = 1;
loopmin[k] = min(loopmin[k], w[root]);
if (vis2[son[root]]) {
loopsize[k] = tms + 1;
loopsum[k] = sum + w[root];
return ;
}
CalcLoopLengthAndSum(son[root], tms + 1, sum + w[root], k);
}
void dfs(int root) {
dealt[root] = 1;
vis[root] = 1;
if (vis[son[root]]) {
tolooptimes[root] = 1;
loopmin[root] = w[root];
toloopsum[root] = w[root];
loopstart[root] = son[root];
toloopmin[root] = w[root];
memset(vis2, 0, sizeof vis2);
CalcLoopLengthAndSum(root, 0, 0, root);
return ;
}
dfs(son[root]);
tolooptimes[root] = tolooptimes[son[root]] + 1;
loopmin[root] = loopmin[son[root]];
toloopmin[root] = min(toloopmin[son[root]], w[root]);
loopsize[root] = loopsize[son[root]];
loopsum[root] = loopsum[son[root]];
toloopsum[root] = toloopsum[son[root]] + w[root];
loopstart[root] = loopstart[son[root]];
}
void Work2() {
memset(toloopmin, 0x7f, sizeof toloopmin);
for (int i = 1; i <= n; ++i) {
if (dealt[i]) continue;
memset(vis, 0, sizeof vis);
dfs(i);
}
// for (int i = 1; i <= n; ++i) {
// printf("#%d fall in loop in %d steps, with mininum weigh %d. Loop size is %d, loop sum is %lld, to loop sum is %lld, loop start at #%d, loop min is %d\n", i, tolooptimes[i], toloopmin[i], loopsize[i], loopsum[i], toloopsum[i], loopstart[i], loopmin[i]);
// }
for (int i = 1; i <= n; ++i) {
// printf("Dealing #%d\n", i);
ll ans = 0;
int few = k, now = i, mini = toloopmin[i];
// printf("set few=%d, now=%d, mini=%d\n", few, now, mini);
if (few > tolooptimes[i]) {
ans += toloopsum[i];
few -= tolooptimes[i];
// printf("Go loop cost %lld, step last %d\n", ans, few);
int m = few / loopsize[i];
// printf("Loop %d times\n", m);
now = loopstart[i];
few -= m * loopsize[i];
ans += m * loopsum[i];
// printf("ans += %d*%lld, few -= %d*%d\n", m, loopsum[i], m, loopsize[i]);
if (m) {
mini = min(mini, loopmin[i]);
// printf("mini update to %d\n", mini);
}
}
// printf("mini update to %d, few last %d\n", mini, few);
for (int j = 1; j <= few; ++j) {
// printf("Steping to %d, weigh %d ", son[now], w[now]);
ans += w[now];
mini = min(mini, w[now]);
now = son[now];
// printf("mini update to %d\n", mini);
}
printf("%lld %d\n", ans, mini);
}
}
int main() {
freopen("pathsjump.in", "r", stdin);
freopen("pathsjump.out", "w", stdout);
scanf("%d %lld", &n, &k);
for (int i = 1; i <= n; ++i) {
scanf("%d", &son[i]);
fa[son[i]] = i;
}
for (int i = 1; i <= n; ++i) {
scanf("%d", &w[i]);
}
if (k <= 100) {
Work1();
} else {
Work2();
}
return 0;
}