Codeforces 1060F Shrinking Tree
題目傳送門
題目大意
給定一棵$n$個點的帶標號樹,不斷執行以下操作:
- 等概率選取一條邊
- 刪掉這條邊的它的兩個端點
- 新建一個點和之前與這兩個點鄰接的點連邊,它的標號從這兩個被刪去的點中等概率選取。
問最後一個點的標號是$1, 2, \cdots, n$的概率。
現在我發現我不但不會設計狀態,還不會設計轉移,一道不錯的題目。(cf的新功能真棒,成功過濾了傻逼題)
不難想到考慮每個點分別作為根的時候的答案。
每次刪邊可以看作將一個點的標號繼承給另一個點, 因此根的不同子樹相互不影響。
注意到選擇邊的方案數一定是$(n - 1)!$,所以將考慮的概率乘上$(n - 1)!$,最後再除掉。(這樣不用考慮選邊的概率,其實這裡換成直接求方案數也可以,只不過可能怕被卡精度)
設$f_{i, j}$表示在當根的標號傳給點$i$的時候,$i$的子樹內還剩下$j$條邊的時候,根標號被保留下來的概率乘上$(n - 1)!$後的結果。
最終我們想要的答案在$f_{root, n - 1}$中。
假設當前我們知道$i$和它部分子樹的答案,考慮合併它的下一個以$u$為根的子樹。
這裡需要討論一下$(i, u)$這條邊在根標記傳到$i$之前還是傳到$i$之後被刪掉的。
假設現在考慮根標記傳到$i$的時候,$u$的子樹中的所有邊和$(u, i)$中還剩下$x$條邊,根標記傳到$u$的時候,$u$的子樹內還剩下$y$條邊。
設根標記傳到$i$的時候,$u$的子樹內的所有邊和$(u, i)$中還剩下$x$條邊,並且根節點的標號被保留的概率乘$(n - 1)!$的結果為$h_{x}$
- 如果$(i, u)$是在根標記傳到$i$之前被刪掉的,當根標記傳到$i$的時候,根標記也傳到了$u$,此時一定滿足$x = y$。再考慮$(i, u)$的刪除時間,顯然它可以插在$u$被刪除的$size_{u} - 1 - x$條邊構成的序列中任何一個位置。這一部分對$h_{x}$的貢獻為$(size_{u} - x)f_{u, x}$。
- 如果$(i, u)$是在根標號傳到$i$之後被刪掉的,當根標記傳到$i$之後,$u$子樹內可能還會刪邊,所以根標記傳到$u$的時候,$u$子樹內剩下的邊數需要小於$x$(因為當根標記傳到$i$的時候$(u, i)$還存在)。當這條邊被刪除的時候,根標號就傳給給$u$,這個事件發生的概率是$\frac{1}{2}$,並且這條邊在$u$的子樹內所有邊刪除結束後刪除掉的。因此這一部分對$h_{x}$的貢獻為$\frac{1}{2}f_{u, y}$。
然後做一個揹包合併。注意一下,合併兩個子樹的時候,需要為刪邊序列分配順序以及被還被刪去的刪去的邊的刪去順序(之前我們只是考慮它們的相對順序)。所以還需要乘上兩個組合數。
Code
1 /** 2 * Codeforces 3 * Problem#1060F 4 * Accepted 5 * Time: 31ms 6 * Memory: 100k 7 */ 8 #include <iostream> 9 #include <cstdlib> 10 #include <cstdio> 11 #include <vector> 12 using namespace std; 13 typedef bool boolean; 14 typedef long double ld; 15 16 const int N = 55; 17 18 template <typename T> 19 void pfill(T* pst, const T* ped, T val) { 20 for ( ; pst != ped; *(pst++) = val); 21 } 22 23 int n; 24 int sz[N]; 25 ld f[N][N]; 26 ld C[N][N]; 27 vector<int> g[N]; 28 29 inline void init() { 30 scanf("%d", &n); 31 for (int i = 1, u, v; i < n; i++) { 32 scanf("%d%d", &u, &v); 33 g[u].push_back(v); 34 g[v].push_back(u); 35 } 36 } 37 38 void dp(int p, int fa) { 39 static ld h[N], tmp[N]; 40 sz[p] = 1, f[p][0] = 1; 41 for (int i = 0, e; i < (signed) g[p].size(); i++) { 42 if ((e = g[p][i]) == fa) 43 continue; 44 dp(e, p); 45 int se = sz[e]; 46 for (int x = 0; x <= se; x++) { 47 h[x] = 0; 48 for (int y = 0; y < x; y++) 49 h[x] += f[e][y] * 0.5; 50 h[x] += f[e][x] * (se - x); 51 } 52 int sum = se + sz[p]; 53 pfill(tmp, tmp + sum + 1, (ld)0); 54 for (int x = 0; x < sz[p]; x++) 55 for (int y = 0; y <= se; y++) 56 tmp[x + y] += f[p][x] * h[y] * C[x + y][x] * C[sum - 1 - x - y][se - y]; 57 copy(tmp, tmp + sum + 1, f[p]); 58 sz[p] = sum; 59 } 60 /* 61 cerr << p << '\n'; 62 for (int i = 0; i < sz[p]; i++) 63 cerr << f[p][i] << " "; 64 cerr << '\n'; 65 */ 66 } 67 68 inline void solve() { 69 ld fac = 1; 70 for (int i = 2; i < n; i++) 71 fac = fac * i; 72 C[0][0] = 1; 73 for (int i = 1; i <= n; i++) { 74 C[i][0] = C[i][i] = 1; 75 for (int j = 1; j < i; j++) 76 C[i][j] = C[i - 1][j] + C[i - 1][j - 1]; 77 } 78 for (int i = 1; i <= n; i++) { 79 pfill(f[1], f[n + 1], (ld)0); 80 dp(i, 0); 81 printf("%.9lf\n", (double) (f[i][n - 1] / fac)); 82 } 83 } 84 85 int main() { 86 init(); 87 solve(); 88 return 0; 89 }
相關推薦
Codeforces 1060F Shrinking Tree - 動態規劃 - 組合數學
題目傳送門 傳送門I 傳送門II 傳送門III 題目大意 給定一棵$n$個點的帶標號樹,不斷執行以下操作: 等概率選取一條邊 刪掉這條邊的它的兩個端點 新建一個點和之前與這兩個點鄰接的點連邊,它的標號從這兩個被刪去的點中等概率選取。
Codeforces 1060F Shrinking Tree
題目傳送門 傳送門I 傳送門II 題目大意 給定一棵$n$個點的帶標號樹,不斷執行以下操作: 等概率選取一條邊 刪掉這條邊的它的兩個端點 新建一個點和之前與這兩個點鄰接的點連邊,它的標號從這兩個被刪去的點中等概率選取。 問最後一個點的標號是$1, 2, \c
Codeforces 1060 F. Shrinking Tree
發現 感覺 劃分 一起 signed 基本功 turn register tro 題目鏈接 一道思維好題啊...感覺這種類型的題很檢驗基本功是否紮實(像我這樣的就掛了)。 題意:你有一棵\(n\)個點的樹,每次隨機選擇一條邊,將這條邊的兩個端點合並,並隨機繼承兩個點標號中的
Codeforces 196C Paint Tree(貪心+極角排序)
cpp namespace paint 進行 滿足 sin its force 一個個 題目鏈接 Paint Tree 給你一棵n個點的樹和n個直角坐標系上的點,現在要把樹上的n個點映射到直角坐標系的n個點中,要求是除了在頂點處不能有線段的相交。 我們先選一個在直角坐標
Codeforces 383C Propagating tree, 線段樹, 黑白染色思想
code namespace ios names seq bit amp mod void 按深度染色,奇深度的點存反權值。 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 vector &
codeforces 1041 E. Tree Reconstruction 和度數有關的構造樹
cos lock .com lis 如果 原來 c++ pla max CF 1041E:http://codeforces.com/contest/1041/problem/E 題意: 告訴你一個樹的節點個數,顯然有n-1條邊。已知去掉一條邊後,兩個集合
cf codeforces round#527F. Tree with Maximum Cost樹形dp
這道題換根時候要計算對答案的影響,就是減去to節點的子樹和sum,加上from節點的子樹和sum(這裡假設to和sum都是一棵樹的根,這棵樹沒有其他部分 #include<bits/stdc++.h> using namespace std; typedef long long ll; i
Codeforces 1092 F Tree with Maximum Cost (換根 + dfs)
題意: 給你一棵無根樹,每個節點有個權值$a_i$,指定一個點u,定義$\displaystyle value = \sum^v a_i*dist(u,v)$,求value的最大值 n,ai<=2e5 思路: 其實就是找一個節點作為根滿足上述最大的value 直接列舉是$O(n^2)$的,肯定
Codeforces 1017G The Tree(分塊DFS)
Codeforces 1017G The Tree 題目大意: 給一個一開始所有節點都是白色的樹,給一些查詢操作,給的三種操作: 1.在v的所有子節點中向下深搜,直到找到第一個白色子孫節點(或者自己),染成黑色。 2.把v的所有子樹(包括它自己)全部
CodeForces 343D Water Tree dfs序 + 線段樹
題意:給定一個樹,樹上有n個點,每個點是一個蓄水池,初始全為空。首先輸入一個n,然後輸入n - 1行,每行兩個點,代表兩點之間有邊,然後輸入一個m,接下來m行操作,操作有3種:1 a,把a及a的所有子孫注水。2 a,把a及a的所有祖先放水。3 a,詢問a點有沒有水,有輸
CodeForces 343D Water Tree(dfs序 線段樹)
題意:給你一顆n個節點的樹,1為根,初始時所有節點都為0,有三種操作: 1 x :將x及其子樹的所有節點都變為1 2 x :將x及其祖先都變為0 3 x :查詢x的值 思路:可以先求出dfs序,對於操作1,我們可以用線段樹區間更新in[x]至out[x];對於操作2,需要
Codeforces 348B - Apple Tree
rst main can apple urn gcd http false div 348B - Apple Tree 我們設最後答案為 x , 我們我們就能用x表示出所有節點下面的蘋果個數, 然後用葉子節點求lcm, 取最大的可行解。 #include<bi
Codeforces 291 E Tree-String Problem AC自動機
mem 。。 麻煩 pll 全部 define efi div pair Tree-String Problem 網上的dfs + kmp 復雜度就是錯的, 除非算出根據下一個字符直接轉移Next數組直接轉移, 而求出Next[ i ][ 26 ]數組和丟進AC自動機裏面
CodeForces - 1118 F2 Tree Cutting
tar sca cli 9.png urn ati 題目 tin 最短 題目傳送門 題解: 先註意到一定存在k種顏色,切成k個塊, 然後要求每個塊內的顏色都一樣,所以可以發現同一種顏色一定在同一個塊內,故任意2個相同顏色的最短路勁上的點的顏色都是該顏色。 我們
Codeforces 1111 E. Tree(虛樹,DP)
cto cond using push end %d inf ces tree 題意 有一棵樹,q個詢問,每次詢問,指定一個點做樹根,再給定k個點,要求把這些點分成不超過m組的方案數,分配的限制是任意兩個有祖先關系的點不能分在同一組。題目還保證了所有的詢問的k加起來不超過
【Codeforces 675D】Tree Construction
put cep 函數 exce com 最小 buffer == static 【鏈接】 我是鏈接,點我呀:) 【題意】 依次序將數字插入到排序二叉樹當中 問你每個數字它的父親節點上的數字是啥 【題解】 按次序處理每一個數字 對於數字x 找到最小的大於x的數
【Codeforces 1149C】Tree Generator?
tree def 想要 spa 每次 公式 上推 inline 父親 Codeforces 1149 C 題意:給一個括號序列,這個括號序列可以生成一棵樹: (:生成一個新的節點,放到當前節點的兒子處。 ):走到當前節點的父親。 現在有\(q\)次操作,每次交換兩個括號的值
Codeforces Round #263 (Div.1) B. Appleman and Tree
ace apple n+1 test right art [0 pan target 題目地址:http://codeforces.com/contest/461/problem/B 題目大意:給一棵樹。每一個點為白色或黑色。切斷一些邊,使得每一個連通塊有且僅有一個黑點
Codeforces 570D TREE REQUESTS dfs序+樹狀數組
stack ott ise ger query numbers mem 1.3 locate 鏈接 題解鏈接:點擊打開鏈接 題意: 給定n個點的樹。m個詢問 以下n-1個數給出每一個點的父節點,1是root 每一個點有一個字母 以下n個小寫字母給出每一個點
(博弈sg) Codeforces Round #417 (Div. 2) E Sagheer and Apple Tree
paths 相同 friend pri 產生 chan star ren have Sagheer is playing a game with his best friend Soliman. He brought a tree with n nodes numbered