Official

B - ネットワーク構築 / Network Construction Editorial by MMNMM


\(3\) 台以上を選んで条件を満たすネットワークを構成できるなら、そのうち \(2\) 台を選んで条件を満たすネットワークを構成できることを示します。

証明

\(k\) 台 \((3\le k)\) 選んで条件を満たすネットワークを構成できたとします。

\(2\) 台を選んで条件を満たすネットワークを構成できることは、ポート数がちょうど \(1\) であるコンピュータが \(2\) つ存在するということです。

\(k\) 頂点の木の辺の本数は \(k-1\) 本なので、選んだコンピュータにおけるポート数の合計は \(2\times(k-1)=2k-2\) です。 木は連結なので、選んだコンピュータのポート数はどれも \(1\) 以上です。

ポート数がどれも \(1\) 以上である \(k\) 個のコンピュータについて、ポート数の合計がちょうど \(2k-2\) となるためには、ポート数がちょうど \(1\) であるコンピュータが \(2\) つ以上存在しなければなりません(そうでなければ、少なくともポート数は \(2k-1\) 以上となってしまいます)。

よって、\(2\) 台を選んで条件を満たすネットワークを構成できることが示されました。

よって、\(1\) 台以上を選んで条件を満たすネットワークを構成できることは、\(1\) 台もしくは \(2\) 台を選んで条件を満たすネットワークを構成できるということです。 さらに言い換えると、これは次のどちらかを満たすことと同値であることがわかります。

  • \(A _ i=0\) であるコンピュータが存在する。
  • \(A _ i=1\) であるコンピュータが \(2\) つ以上存在する。

あとは、この条件を満たすか for 文などで判定を行うことでこの問題を解くことができます。

実装例は以下のようになります。

#include <iostream>
using namespace std;

int main() {
    int N;
    cin >> N;
    // ポート数が 0 のコンピュータの個数とポート数が 1 のコンピュータの個数をそれぞれ数える
    int zero = 0, one = 0;
    for (int i = 0; i < N; ++i) {
        int a;
        cin >> a;
        if (a == 0) {
            ++zero;
        }
        if (a == 1) {
            ++one;
        }
    }
    // 条件を判定して出力
    if (zero < 1 && one < 2) {
        cout << "No" << endl;
    } else {
        cout << "Yes" << endl;
    }
    return 0;
}
N = int(input())

# ポート数が 0 のコンピュータの個数とポート数が 1 のコンピュータの個数をそれぞれ数える
zero = 0
one = 0
for a in map(int, input().split()):
    if a == 0:
        zero += 1
    if a == 1:
        one += 1

# 条件を判定して出力
if zero < 1 and one < 2:
    print('No')
else:
    print('Yes')

posted:
last update: