AGC009-B:Tournament

問題

https://beta.atcoder.jp/contests/agc009/tasks/agc009_b

考え方

木DPだが、遷移が重要。今ある親 u から 4 個の子 (v_1, v_2, v_3, v_4)をもつ部分木の場合を考える。ある頂点の深さを cost[p] としておく。

f:id:d_tutuz:20181009051702p:plain

このとき、トーナメントの割当としては以下のようになる。

f:id:d_tutuz:20181009051710p:plain

u は v_1, v_2, v_3, v_4 のいずれとも試合をするが、このとき u の深さが最適に(一番浅く)なるときは、深い場所に一番浅い頂点をもつように、すなわち cost[v_1] >= cost[v_2] >= cost[v_3] >= cost[v_4] となるように割り当てるのが最適である。

このとき u の深さ cost[u] は cost[v_k] を降順にソートしておいて cost[u] = cost[v_k] + k+1 となる

       List<Integer>[] g;
        public void solve(int testNumber, InputReader in, PrintWriter out) {

            int n = in.nextInt();
            g = new ArrayList[n];
            g = Stream.generate(ArrayList::new).limit(n).toArray(List[]::new);

            for (int i = 1; i < n; i++) {
                int a = in.nextInt()-1;
                g[a].add(i);
            }
            int ans = dfs(0);
            out.println(ans);

        }

        int dfs(int now) {

            List<Integer> list = new ArrayList<>();
            for (int next : g[now]) {
                list.add(dfs(next));
            }
            Collections.sort(list, Comparator.reverseOrder());
            int ret = 0;
            for (int i = 0; i < list.size(); i++) {
                ret = Math.max(ret, i+1 + list.get(i));
            }

            return ret;
        }

ポイント

  • 実験して遷移を考える

類題