CF696B Puzzles


Description

Barney lives in country USC (United States of Charzeh). USC has n cities numbered from 1 through n and n - 1 roads between them. Cities and roads of USC form a rooted tree (Barney’s not sure why it is rooted). Root of the tree is the city number 1. Thus if one will start his journey from city 1, he can visit any city he wants by following roads.

Some girl has stolen Barney’s heart, and Barney wants to find her. He starts looking for in the root of the tree and (since he is Barney Stinson not a random guy), he uses a random DFS to search in the cities. A pseudo code of this algorithm is as follows:

let starting_time be an array of length n 
current_time = 0 
dfs(v): 
current_time = current_time + 1 
starting_time[v] = current_time 
shuffle children[v] randomly (each permutation with equal possibility) 
// children[v] is vector of children cities of city v 
for u in children[v]: 
dfs(u) 

As told before, Barney will start his journey in the root of the tree (equivalent to call dfs(1)).
Now Barney needs to pack a backpack and so he wants to know more about his upcoming journey: for every city i, Barney wants to know the expected value of starting_time[i]. He’s a friend of Jon Snow and knows nothing, that’s why he asked for your help.

下面是譯文:

Bob和Alice出去度蜜月,但Alice不慎走失,Bob在傷心過后,決定前去尋找Alice。
他們度蜜月的地方是一棵樹,共有N個節點,Bob會使用下列DFS算法對該樹進行遍歷。

starting_time是一個容量為n的數組
current_time = 0
dfs(v):
current_time = current_time + 1
starting_time[v] = current_time
將children[v]的順序隨機排列 (每個排列的概率相同)
// children[v]v的直接兒子組成的數組
for u in children[v]:
dfs(u)

1是這棵樹的根,Bob會從1出發,即運行dfs(1),現在他想知道每個點starting_time的期望值。

終於把這道題搞出來了... 汪汪大哭

真的是一道很好的期望dp題目

將到達每個節點$u$的期望時間戳記為$ans[u]$ 因為他是隨機$dfs$所以他的兄弟節點會對他的期望時間戳產生貢獻

橫向來看 只看該節點與他的兄弟節點 將其父親的兒子個數記為$m$ 也就是包括他自己的兄弟節點的個數

假設他在當前兄弟的$dfs$序中排名為$i$ 那么其余的每個兄弟節點排在他前面的概率是$\frac{i - 1}{m - 1}$

所以每個兄弟節點$bro$對他產生的貢獻為$\frac{i - 1}{m - 1}\cdot size[bro]$ 

那么總貢獻為 $\frac{i - 1}{m - 1}\cdot \sum_{bro \neq  u}size[bro]$ 

將$\sum_{bro \neq  u}size[bro]$ 記作$sum$ 易知$sum = size[fa] - size[u] - 1$ 減一是因為減去該子樹的根節點

顯然 節點$u$排名為$i$的情況的概率為$\frac{1}{m}$

所以$ans[u] = \frac{1}{m}\cdot \sum_{i = 1}^{m}\frac{i - 1}{m - 1}\cdot sum$

化簡得 $ans[u] = \frac{1}{2}\cdot sum$

最后$ans[u] += ans[fa] + 1$ 加一是加上前面訪問完了之后下一步走到$u$的步數

代碼

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

const int N = 1e6 + 5;
int size[N], sum[N], head[N], nex[2 * N], tov[2 * N], n, tot;
double ans[N];

void add(int u, int v) {
    
    tot ++;
    nex[tot] = head[u];
    tov[tot] = v;
    head[u] = tot;
}

void dfs(int u, int fa) {
    
    size[u] = 1;
    for(int i = head[u];i;i = nex[i]) {
        int v = tov[i];
        if(v == fa) continue;
        dfs(v, u);
        size[u] += size[v];
    }
    for(int i = head[u];i;i = nex[i]) {
        int v = tov[i];
        if(v == fa) continue;
        sum[v] = size[u] - size[v] - 1;
    }
}

void Add_Edge( ) {
    
    scanf("%d",& n);
    for(int i = 1;i < n;i ++) {
        int fa;
        scanf("%d",& fa);
        add(fa, i + 1); add(i + 1, fa);
    }
    dfs(1, 1);
}

void Dfs(int u, int fa) {
    
    for(int i = head[u];i;i = nex[i]) {
        int v = tov[i];
        if(v == fa) continue;
        ans[v] = ans[u] + 1 + 0.5 * sum[v];
        Dfs(v, u);
    }
}

int main( ) {
    
    Add_Edge( );
    ans[1] = 1; Dfs(1, 1);
    for(int i = 1;i <= n;i ++) printf("%.1lf ", ans[i]);
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM