[アルゴリズム分析]-典型的なツリーの問題

ロープと重量

トピック

番号が付けられた0~n-1ロープn個あり、各ロープはw[i]重い物体で結ばれています。c[i]ロープの最大重量はです。各ロープは他のロープの下に吊るすか、フックに直接掛けることができます(番号-1)。 )、ロープの下にあるすべての重りの重量の合計がロープの最大荷重よりも大きい場合、それは壊れます。各ロープに荷重、重りの重さ、および荷重数を順番に与え、表示されずに最大で何本のロープを吊るすことができるかを尋ねますロープが切れている状況。

分析

二分法の答え:与えられた数のロープについて、dfsはツリー全体をトラバースし、各ノードの負荷を見つけて、それが壊れるかどうかをチェックします。時間の複雑さはO(n)、であり、合計の時間の複雑さはO(nlogn)です。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n, c[50005], w[50005], p[50005], h[50005];
vector<int> g[50005];
int dfs(int x) {
    
    
    h[x] = w[x];
    for (auto i : g[x]) {
    
    
        if (!dfs(i)) return 0;
        h[x] += h[i];
    }
    return h[x] <= c[x];
}
int chk(int x) {
    
    
    for (int i = 0; i <= x; i++)
        g[i].clear();
    for (int i = 1; i <= x; i++)
        g[p[i]].push_back(i);
    return dfs(0);
}
int main() {
    
    
    cin >> n;
    c[0] = 1e18; w[0] = 0;
    for (int i = 1; i <= n; i++) {
    
    
        cin >> c[i] >> w[i] >> p[i];
        p[i] += 1;
    }
    int lo = 1, hi = n, mid;
    while (lo < hi) {
    
    
        mid = lo + (hi-lo+1) / 2;
        if (chk(mid))
            lo = mid;
        else
            hi = mid-1;
    }
    cout << lo << endl;
    return 0;
}

木の距離の合計

トピック

番号が付けられた1~nn個のノードで構成されるルート化されていないツリーが与えられた場合、ノードごとに、他のノードまでの距離の合計を求めます。

分析

ルートとして1つの(たとえば、番号1)ノードを選択し、son [i]を定義して、必要なノード番号iをルートとするサブツリー内のノードの数を表しdp[i]ます。最初のdfs統計がson[i]計算されますdp[1]。これは、途中計算でき、その後、再帰的に計算できますxが非ルートノードであり、その親ノードがyでありdp[y]、計算されているとすると、計算dp[x]は2つの部分に分割できます。xをルートとするサブツリー内のノード、xまでの距離はyまでの距離より1だけ小さい、など。son[x]1つのノードがあります。他のノードはyよりもxまでの距離1つ長く、(n-num[x])そのようなノードが1つあります

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int n, son[100005];
vector<int> g[100005];
LL dp[100005];
void dfs1(int x, int p, int d, LL &sum) {
    
    
    sum += d;
    son[x] = 1;
    for (auto i : g[x]) if (i != p) {
    
    
        dfs1(i, x, d+1, sum);
        son[x] += son[i];
    }
}
void dfs2(int x, int p) {
    
    
    if (p > 0)
        dp[x] = dp[p] + n - 2 * son[x];
    for (auto i : g[x]) if (i != p) {
    
    
        dfs2(i, x);
    }
}
int main() {
    
    
    cin >> n;
    for (int i = 1; i < n; i++) {
    
    
        int x, y;
        cin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    dfs1(1, -1, 0, dp[1]);
    dfs2(1, -1);
    for (int i = 1; i <= n; i++)
        cout << dp[i] << endl;
    return 0;
}

リソースポータル

  • [入札プログラムの猿になる]パブリックアカウントに注意してください
  • [入札プログラムの猿になる]パブリックアカウントの背景にある[pythoninformation] [2020 Autumn Recruitment]に返信して、対応するサプライズを入手してください。

「❤️みんなありがとう」

  • より多くの人がこのコンテンツを見ることができるように、それをサポートしたい(あなたがそれを気に入らなければ、それはすべてフーリガンです-_-)
  • メッセージエリアで私とあなたの考えを共有することを歓迎します、そしてあなたはメッセージエリアであなたの考えのプロセスを記録することも歓迎します。

おすすめ

転載: blog.csdn.net/ywsydwsbn/article/details/109261127