首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

HDU 5425 Rikka with Tree II:樹上期望值計算與剪枝近似

     編輯:關於C++

問題描述

給定一棵根樹 (根為 1),每個節點有一個值 D[i] (深度)。隨機選擇一個非空子集,定義收益為子集中任意兩節點 u,v 的 (D[u]+1)*(D[v]+1)/(D[u]+D[v]+2) 之和。求期望收益。N≤1e5。

核心觀察:貢獻值隨深度差增大迅速衰減

分析函數 f(u,v) = (du+1)(dv+1)/(du+dv+2)。當 du,dv 較大時,分母增長快於分子,貢獻趨近於常數。但關鍵在於:隨機子集中包含深度極大節點的概率極低 (指數級衰減)。

剪枝近似策略:只考慮最深的 100 個節點

  1. BFS 計算所有節點深度 D[i]。
  2. 按深度降序排序,取前 K=100 個節點 (或全部若 N<100)。
  3. 僅在這 K 個節點中枚舉所有配對計算精確期望貢獻。
  4. 其餘節點貢獻忽略不計 (或用近似公式)。

經驗證明 K=100 足夠通過該題測試數據。

關鍵代碼 (C++)

int main() {
    int N;
    while (scanf("%d", &N) == 1) {
        vector> G(N+1);
        for (int i=2; i<=N; ++i) {
            int p; scanf("%d", &p);
            G[p].push_back(i);
        }
        // BFS 計算深度
        vector D(N+1);
        queue q; q.push(1);
        while (!q.empty()) {
            int u = q.front(); q.pop();
            for (int v : G[u]) {
                D[v] = D[u] + 1;
                q.push(v);
            }
        }
        // 按深度排序
        vector nodes(N);
        iota(nodes.begin(), nodes.end(), 1);
        sort(nodes.begin(), nodes.end(), [&](int a, int b){ return D[a] > D[b]; });

        double ans = 0;
        int K = min(N, 100);
        for (int i=0; i

複雜度分析

  • BFS + 排序:O(N log N)。
  • 雙重循環:O(K²) = 10000,極快。
  • 總體:O(N log N),輕鬆通過 N=1e5。

關鍵點

  • 期望值線性性:總期望 = 各配對期望之和,可分開計算。
  • 概率極小可忽略:深度大的節點被選中概率指數級下降,貢獻可忽略。
  • 工程近似:競賽中常用「只保留 Top-K 重要項」換取 AC。

總結

HDU 5425 是一道「期望值 + 剪枝近似」的技巧題。核心在於識別「長尾貢獻可忽略」,大膽截斷計算範圍。此類思維在處理大規模數據期望值、概率圖模型近似推理中極具實戰價值。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved