Challenge: Connect the country

Subdomeniu: Probability (probability)

Scor cont: 60.0 / 60

Submission status: Accepted

Submission score: 1.0

Submission ID: 464755747

Limbaj: cpp14

Link challenge: https://www.hackerrank.com/challenges/connect-the-country/problem

Cerinta

We have a country containing _N _cities. Each day we choose 2 cities such that there is no road between them and build a road between them. We choose each pair of nonadjacent cities with equal probability. Let X be the number of days before we obtain a connected country. What is the expected value of X? Output the integer part of answer.

Input Format

First line of input as an integer N.

Output Format

Print an integer being the result of the test.

Constraints

+ $N <= 30$

Cod sursa

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

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N;
    cin >> N;

    int maxM = N * (N - 1) / 2;

    // Binomial coefficients up to C(maxM, *), stored as long double.
    vector<vector<long double>> C(maxM + 1, vector<long double>(maxM + 1, 0.0L));
    for (int i = 0; i <= maxM; ++i) {
        C[i][0] = C[i][i] = 1.0L;
        for (int j = 1; j < i; ++j) C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
    }

    vector<int> M(N + 1, 0);
    for (int n = 0; n <= N; ++n) M[n] = n * (n - 1) / 2;

    // conn[n][m] = number of connected labeled graphs with n vertices and m edges.
    vector<vector<long double>> conn(N + 1);
    for (int n = 0; n <= N; ++n) conn[n].assign(M[n] + 1, 0.0L);
    conn[1][0] = 1.0L;

    for (int n = 2; n <= N; ++n) {
        int Mn = M[n];
        for (int m = 0; m <= Mn; ++m) {
            long double val = C[Mn][m]; // all graphs with n vertices and m edges

            // Subtract disconnected graphs by fixing component containing vertex 1.
            for (int k = 1; k <= n - 1; ++k) {
                long double pick = C[n - 1][k - 1];
                int Mk = M[k];
                int Mr = M[n - k];

                int eL = max(0, m - Mr);
                int eR = min(m, Mk);
                if (eL > eR) continue;

                long double sum = 0.0L;
                for (int e = eL; e <= eR; ++e) {
                    sum += conn[k][e] * C[Mr][m - e];
                }
                val -= pick * sum;
            }

            if (val < 0.0L && fabsl(val) < 1e-12L) val = 0.0L;
            conn[n][m] = val;
        }
    }

    int Mn = M[N];
    long double expected = 0.0L;
    for (int m = 0; m < Mn; ++m) {
        long double pConnected = conn[N][m] / C[Mn][m];
        if (pConnected < 0.0L) pConnected = 0.0L;
        if (pConnected > 1.0L) pConnected = 1.0L;
        expected += (1.0L - pConnected);
    }

    long long ans = (long long)floor(expected + 1e-12L);
    cout << ans << '\n';
    return 0;
}
HackerRank Probability – Connect the country