Problem p02585 (C++) — buggy submission, verdict: Runtime Error

#include <algorithm>
#include <cstdint>
#include <iostream>
#include <vector>
using namespace std;

int main() {
  int n, k;
  cin >> n >> k;
  vector<int> p(n), c(n);
  for (auto &e : p)
    cin >> e;
  for (auto &e : c)
    cin >> e;

  int64_t ans = -1e18;

  for (int i = 0; i < n; ++i) {
    vector<int> cycle;
    int cpos = i;
    int64_t csum = 0;

    do {
      cpos = p[cpos] - 1;
      cycle.push_back(c[cpos]);
      csum += c[cpos];
    } while (cpos != i);

    int64_t ians = 0;

    if (0 < csum) {
      int64_t pmax = -1e18, psum = 0;
      for (int j = 0; j < cycle.size() && j < k; ++j) {
        psum += cycle[j];
        pmax =
            max(pmax, (int64_t)(psum + csum * ((k - (j + 1)) / cycle.size())));
      }
      ians += pmax;

      // プラス側のコードが間違っている？
      /*ians += csum * (k / cycle.size());
      int64_t pmax = 0, psum = 0;
      for (int j = 0; j < k % cycle.size(); ++j) {
          psum += cycle[j];
          pmax = max(pmax, psum);
      }
      ians += pmax;*/
    } else {
      int64_t mmax = cycle[0], msum = cycle[0];
      for (int j = 1; j < min((size_t)k, cycle.size()); ++j) {
        msum += cycle[j];
        mmax = max(mmax, msum);
      }
      ians += mmax;
    }

    ans = max(ans, ians);

    /*
    int64_t ians = 0;
    int rest = k;

    if (0 < csum && cycle.size() < rest) {
        ians = csum * (rest / cycle.size());
        rest %= cycle.size();
    }

    int j = 0;
    int64_t pans = 0;
    int64_t psum = 0;
    if (csum <= 0) {
        j = 1;
        pans = cycle[0];
        psum = cycle[0];
    }

    while (j < min((size_t)rest, cycle.size())) {
        psum += cycle[j];
        pans = max(pans, psum);
        ++j;
    }

    ians += pans;

    ans = max(ans, ians);
    */
  }

  cout << ans << endl;
}


Error: 0

Fixed submission:

#include <cstdint>
#include <iostream>
#include <vector>
using namespace std;

// サイクルでのスコアの総和がプラスなら、サイクル内の頂点数をSとして、
// S/K回(整数演算)のサイクルの総和と、
// S%K回(整数演算)まででたどり着くうち、スコアの総和が最大化される頂点の範囲を探索。
// これがその頂点を選んだ際の最大値となる。
//
// これをすべての頂点に行い、最大値を求める。
//
// すべての頂点(N)について、サイクルの探索(高々N)を行うため O(N^2)

int main() {
  int n, k;
  cin >> n >> k;
  vector<int> p(n), c(n);
  for (auto &e : p)
    cin >> e;
  for (auto &e : c)
    cin >> e;

  // 最低1回マスを移動するために、必ず1回は更新される値を設定
  int64_t ans = -1e18;

  // すべての頂点に対して、その頂点から出発した時の最大スコアを求める
  for (int i = 0; i < n; ++i) {
    // サイクル内のそれぞれの頂点から移動した際の獲得スコア
    vector<int> score;
    // 現在頂点から開始した際に得る、最大スコア
    int64_t max_score = 0;
    // サイクル内の獲得スコアの総和
    int64_t sum = 0;
    // 現在の頂点
    int pos = i;

    // サイクル探索
    do {
      // 次の頂点へ移動
      pos = p[pos] - 1;
      // 次の頂点へのスコアを登録
      score.push_back(c[pos]);
      // 総和に加算
      sum += c[pos];
    } while (pos != i);

    // スコアの総和がプラスであり、
    // サイクルの頂点数がkより少ない(少なくとも1回はサイクルを回りきれる)ならば
    int rest = k;
    if (0 < sum && score.size() < rest) {
      // サイクルを回れるだけ回る
      max_score = sum * (rest / score.size());
      // サイクルを回ったあまりが残りの動ける回数
      rest %= score.size();
    }

    // 残り移動回数でたどり着ける頂点のうち、スコアの総和が最大となるものを計算
    // 最低1回マスを移動するために、必ず1回は更新される値を設定
    int64_t part_score = -1e18;
    int64_t part_sum = 0;
    for (int i = 0; i < rest; ++i) {
      part_sum += score[i];
      part_score = max(part_score, part_sum);
    }

    // 残りの移動分を足す
    max_score += part_score;

    // 最大値を更新
    ans = max(ans, max_score);
  }

  cout << ans << endl;
}