C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++で木の任意の2頂点間の次数の積の合計を最大化する

問題概要

整数Nが与えられたとき、N個の頂点を持つ木を構築し、すべての順序付きペア(x, y)(ただしx ≠ y)に対する degree(x) × degree(y) の合計が最大になるようにするのが本記事の目的です。

入力: N = 5

出力: 50

計算例

葉の数を最小限に抑えた木は、次のような鎖状(パス)の構造になります。

1 - 2 - 3 - 4 - 5

各頂点の次数は次のとおりです。

頂点1の次数 = 1
頂点2の次数 = 2
頂点3の次数 = 2
頂点4の次数 = 2
頂点5の次数 = 1

すべての順序付きペア(x, y)に対する次数の積は以下のように計算できます。

頂点1 = 1×2 + 1×2 + 1×2 + 1×1 = 7
頂点2 = 2×1 + 2×2 + 2×2 + 2×1 = 12
頂点3 = 2×1 + 2×2 + 2×2 + 2×1 = 12
頂点4 = 2×1 + 2×2 + 2×2 + 2×1 = 12
頂点5 = 1×2 + 1×2 + 1×2 + 1×1 = 7
合計 = 50

入力: N = 7

出力: 122

解法のアプローチ

  • 木に含まれるすべての頂点の次数の合計は 2N − 2 になります(Nは頂点数)。この合計を最大化するには、葉(次数1の頂点)の数を最小化する必要があります。
  • Max() 関数内で sum を 0 で初期化し、x と y について二重ループを作成します。
  • ループ内では、まず x == y であるかを判定し、該当する場合は continue でスキップします。
  • それ以外の場合、degreeX を 2 で初期化し、x が葉または根(x == 1 または x == N)であれば degreeX を 1 に設定します。y についても同様に degreeY を求めます。
  • 最後に sum += (degreeX * degreeY) で合計を更新し、ループ終了後に結果を返します。

C++での実装例

#include <bits/stdc++.h>
using namespace std;

int Max(int N){
    int sum = 0;
    for (int x = 1; x <= N; x++){
        for (int y = 1; y <= N; y++){
            if (x == y)
                continue;
            // 頂点xの次数を2で初期化
            int degreeX = 2;
            // xが葉または根の場合
            if (x == 1 || x == N)
                degreeX = 1;
            // 頂点yの次数を2で初期化
            int degreeY = 2;
            // yが葉または根の場合
            if (y == 1 || y == N)
                degreeY = 1;
            // 合計を更新
            sum += (degreeX * degreeY);
        }
    }
    return sum;
}

int main(){
    int N = 5;
    cout << Max(N);
}

出力結果

上記のコードを実行すると、次の出力が得られます。

50

補足: O(1)で求める数式

この問題は数式を使えば定数時間で解くことも可能です。次数が「1, 2, 2, …, 2, 1」となるパス状の木では、次数の総和は 2N − 2、次数の2乗の総和は 2×1² + (N−2)×2² = 4N − 6 となります。順序付きペア全体の積の総和は「(次数の総和)² − (次数の2乗の総和)」で表されるため、次の式が成り立ちます。

答え = (2N − 2)² − (4N − 6) = 4N² − 12N + 10

N = 5 の場合は 4×25 − 60 + 10 = 50、N = 7 の場合は 196 − 84 + 10 = 122 となり、実際の結果と一致することを確認できます。

  1. C++で二分木における最も近い葉ノードまでの距離を求める方法

    二分木が与えられ、その葉ノードはそれぞれ異なるレベルに存在するとします。さらに、あるノードを指すポインタが与えられ、そのノードから最も近い葉ノードまでの距離を求める必要があります。例として、次のような二分木を考えてみましょう。この木における葉ノードは 2、-2、6 の3つです。もしポインタがノード -5 を指している場合、-5 から最も近い葉ノードまでの距離は 1 となります。解決のアプローチこの問題を解くには、次の手順で考えます。まず、指定されたノードを根とする部分木を走査し、その部分木内で最も近い葉ノードを見つけて距離を記録します。次に、木の根から全体を走査します。ノード x が左部分木に

  2. 【C++】二分木内の任意の2つのノード間のパスを出力する方法

    はじめに 本記事では、C++プログラミングにおいて二分木(バイナリツリー)内の任意の2つのノード間のパス(経路)を出力する方法を解説します。 前提として、すべてのノードが互いに異なる値を持つ二分木が与えられ、その中から指定した2つのノードをつなぐ経路を出力することを目標とします。 例として、次のような二分木を考えます。 具体例: ノード140からノード211までの経路を出力したい場合、期待される出力は以下の通りです。 Output: 140->3->10->211 解決のアプローチ 基本的なアイデアは、「ルートノードから目的の2つのノードそれぞれへの経路」を求め、それらを