問題P5021 [建設]トラックへのソリューション - ロックウェルバレー

この質問は(つまり少し木のDPでありますギャング光スプレー

この質問は唯一この質問への半分の答えを知っているとき、私はちょうどないアイデアを持っていません

なぜ半分答えは?

トピック:

現在、トラックのプログラムの構造は決定されていません。あなたの仕事は設計することである
種トラック構築スキームを、そのような点でトラック建設メートルの長さ
のトラックの最小の最大長さ
(すなわち、トラックが最短トラックmの
長さをできるだけ大きく)

最小または最大の...... ......最大値は通常、最低でも起こる半分の答えです。

どのように二分答えは?

この質問は、最低限の要求されたの長さ、それがなければなりません最大の
半分の長さ、それは我々が設定し始めることができるときであります

l = 0, r = 最大值  mid = (l + r) / 2

我々は半ば有効呼び出す各トラックに等しいより大きな長さを取得し、そして有効トラック数がmより大きければ、次に説明ミッド<=真の答えので、我々は、Lせ=ミッド+ 1、2点が続き、さもなければR =半ばをしましょう。

どのように転送するには?

実際には、ブラインドの始まりは、私は、これは木のDP(エスケープであることがわかっていないんとき

そのようなマップがあり、私たちは各サブツリーを検討し始め

我々は5-2から、に根ざしたこのノード2サブツリーと仮定して、このパス7は、我々は、これら2つのエッジは、その後、削除、直接答えを追加することができ、トラックの法的な条件を満たすことです。

これは、いくつかの残りの側面かもしれません。

我々は最初に6であると想定(私たちは、あなたがこのノード2を使用している場合、トラックの法的な長さを構成していることがわかります、いずれか2ノードはCouchu法的な長さに0から上がるために開始し、いずれかの以下の側2を選びます2つの辺)までは、私たちが最も長い辺を使用したことがない選択しなければなりません、唯一の側を選ぶことができ、中に参加します。

N = 50000、我々はあなたが1辺の法的側面を作ることができれば、各ノードの整然としたLOWER_BOUNDマルチセット側を達成し、見つけるために使用することができます。

これには、達成することができます

int dfs(int x, int fa, int mid) {
    int len = 0;
    multiset<int> s;
    for (int i = p[x]; i != -1; i = e[i].nxt) {
        int v = e[i].v, w = e[i].w, l;
        if (v == fa) {
            continue;
        }
        l = dfs(v, x, mid) + w;
        opt[x] += opt[v];
        if (l >= mid) {
            opt[x]++;
        } else {
            s.insert(l);
        }
    }
    while (!s.empty()) {
        int now = (*s.begin());
        s.erase(s.begin());
        multiset<int>::iterator it = s.lower_bound(mid - now);
        if (it != s.end()) {
            s.erase(it);
            opt[x]++;
        } else {
            len = now;
        }
    }
    return len;
}

図菊の言葉が引っかかることのよう?私は、あなたが懸念している場合は特に、あなたは一度だけ、それを判断することができ、その後、ソートLOWER_BOUND OK、試していません。

8.19更新

有同学不知道菊花图是什么

就是介个东西QWQ

菊花图通常会被卡,所以需要特判或者寻找更高效算法( 一般是特判辣, 因为菊花图上的问题大部分比较简单的 )

好像也没多少树上dp

おすすめ

転載: www.cnblogs.com/with6676/p/11517825.html