舞台装置の魔女 (AOJ 2318)

http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=2318

問題

解法

解説参照。

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <queue>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

int n, m, T;
int dp[310];
vector<int> akuma[310]; // 自分自身がfromとなっているedgeのindexの集合
int edgeCount[1100];
int edgeTo[1100];
vector<int> edgeFrom[1100];

void Push(priority_queue<pair<int, int> > &que, int index) {
  int e = edgeFrom[index].size();
  vector<int> costs(e);
  REP(i, e) {
    costs[i] = dp[edgeFrom[index][i]];
  }
  sort(costs.rbegin(), costs.rend());
  int ans = 0;
  REP(i, e) {
    ans = max(ans, costs[i] + i);
  }
  que.push(make_pair(-ans, edgeTo[index]));
}

int main() {
  while (scanf("%d %d %d", &n, &m, &T) > 0) {
    // initialize
    T--;
    MEMSET(dp, -1);
    REP(i, 310) { akuma[i].clear(); }
    REP(i, 1100) { edgeFrom[i].clear(); }
    MEMSET(edgeCount, 0);
    MEMSET(edgeTo, -1);
    priority_queue<pair<int, int> > que;

    // input
    REP(i, n) {
      int leaf;
      int v = scanf("%d", &leaf);
      assert(v == 1);
      if (leaf == 1) {
        que.push(make_pair(-1, i));
      }
    }
    REP(i, m) {
      int k, to;
      int v = scanf("%d %d", &to, &k);
      assert(v == 2);
      to--;
      edgeTo[i] = to;
      edgeCount[i] = k;
      REP(j, k) {
        int from;
        int v = scanf("%d", &from);
        assert(v == 1);
        from--;
        edgeFrom[i].push_back(from);
        akuma[from].push_back(i);
      }
    }

    // process
    while (!que.empty()) {
      int node = que.top().second;
      int cost = -que.top().first;
      que.pop();
      if (dp[node] != -1) { continue; }
      dp[node] = cost;
      FORIT(it, akuma[node]) {
        edgeCount[*it]--;
        assert(edgeCount[*it] >= 0);
        if (edgeCount[*it] == 0) {
          Push(que, *it);
        }
      }
    }
    //REP(i, n) {
    //  cout << dp[i] << " ";
    //}
    //cout << endl;
    printf("%d\n", dp[T]);
  }
}