TopCoder SRM620: RandomGraph
ある1つの頂点 \(X\) に着目したとき、その頂点がサイズ3以下の連結成分に含まれる時のパターンは以下の5つになる。
- 連結成分が1つの場合
- 連結成分が2つの場合
- 連結成分が3つの場合 - \((X, Y), (Y, Z)\) のように枝が伸びている場合
- 連結成分が3つの場合 - \((X, Y), (X, Z)\) のように枝が伸びている場合
- 連結成分が3つの場合 - \((X, Y), (X, Z), (Y, Z)\) のように枝が伸びている場合
DP[n] = 「n 頂点のグラフが サイズ3以下の連結成分だけで構成されている確率」とすると
DP[n] = 「これらのパターンに収まる確率 × その連結成分を除外した頂点がサイズ3以下の連結成分だけで構成されている確率」の和
のように漸化式を構築できるので、これを使って動的計画法を適用する。 \(O(n)\)
public class RandomGraph { public double probability(int n, double p) { var dp = new double[n + 1]; p /= 1000; for (int i = 0; i <= n; i++) { if (i <= 3) dp[i] = 1.0; else { double val = 0; // 0 edge : a val += Math.Pow(1 - p, i - 1) * dp[i - 1]; // 1 edge : a - b val += (i - 1) * Math.Pow(1 - p, (i - 2) * 2) * p * dp[i - 2]; // 2 edge: b - a - c val += (i - 1) * (i - 2) / 2 * Math.Pow(1 - p, (i - 3) * 3) * p * p * (1 - p) * dp[i - 3]; // 2 edge: a - b - c val += (i - 1) * (i - 2) * Math.Pow(1 - p, (i - 3) * 3) * p * p * (1 - p) * dp[i - 3]; // 3 edge: a-b, b-c, c-a val += (i - 1) * (i - 2) / 2 * Math.Pow(1 - p, (i - 3) * 3) * p * p * p * dp[i - 3]; dp[i] = val; } } return 1 - dp[n]; } }