n<=50000的樹,深度<=100,有點權,選兩個點x,y,使
最小。dis取了min之後,整個樹就會以某條邊為分界線分成兩半,一半歸乙個點管。如果是兩棵完全獨立的樹的話,那肯定分別取這兩棵樹的帶權重心。但割掉某條邊再找兩邊重心,這種情況不一定是合法情況。例如:
上圖中,虛線邊被斷開,兩邊的重心分別是星標節點。這不是乙個合法方案,但它顯然不如乙個合法方案的答案優:
所以放心大膽地割就好了。注意到本題中樹的深度h很小,所以割邊後涉及的子樹資訊修改操作都可以暴力修改。
把樹以某點為根,希望能預處理出一些資訊使得能夠在o(h)的時間內找到割完邊每一半的重心。如果是普通的一棵樹,知道了子樹大小(權值和)之後,從某點出發最多走2h步之後就可以到重心。割了某條邊之後,乙個點最多隻會有一棵子樹資訊被修改。因此記最大兒子和次大兒子即可。
至於答案的記錄我寫的有點醜。如果想的話可以看一下我怎麼寫的,不然就直接看怎麼寫更方便吧。所有子樹大小加起來即為根節點為重心的總代價,因為這樣加起來,越是下面的點加的次數越多。斷掉某條邊之後,修改子樹大小的同時可修改根節點為重心答案,然後從根節點開始向重兒子走,只要比較最大兒子和次大兒子子樹權和即可,邊走邊改答案。走一步,就是走到的這棵子樹權值和少算一次,其外面的權值和多算一次。
我是記了每個節點為根的答案。。式子有點亂。。
1 #include2 #includeview code3 #include4 #include5
//#include6//
#include
7using
namespace
std;89
intt,n;
10#define maxn 50011
11struct edgeedge[maxn<<1];int
first[maxn],le,val[maxn];
12void
in(int x,int y)
13void insert(int x,int y)
14void
init()
1524
for (int i=1;i<=n;i++) scanf("
%d",&val[i]);25}
26#define ll long long
27int
size[maxn],dep[maxn],f[maxn],tot,hea[maxn],h2[maxn];ll aa[maxn];
28void dfs(int x,int
fa)2940}
41int
main()
4250
for (int i=f[x],cnt=1;i;i=f[i],cnt++) size[i]-=size[x],aa[i]-=aa[x]+1ll*cnt*size[x];
51 tot-=size[x];
52 ll ans=0,qq=0;53
for (int now=1
;;)54
59if (size[hea[now]]>size[h2[now]] && hea[now]!=x) now=hea[now],
60 qq+=aa[f[now]]-(aa[now]+size[now])+tot-size[now];
61else now=h2[now],qq+=aa[f[now]]-(aa[now]+size[now])+tot-size[now];62}
63 qq=0;64
for (int now=x;;)
6567 now=hea[now],qq+=aa[f[now]]-(aa[now]+size[now])+size[x]-size[now];68}
69 ans=min(ans,ans);
70 tot+=size[x];
71for (int i=f[x],cnt=1;i;i=f[i],cnt++) size[i]+=size[x],aa[i]+=aa[x]+1ll*cnt*size[x];72}
73 printf("
%lld\n
",ans);
74return0;
75 }
BZOJ 3566 SHOI2014 概率充電器
題目 題意 給定樹形結構的n個元件,每個元件有一定概率自己充電,還有一定概率通過某條邊給其他元件充電,求充電的元件期望個數。n 500000 題解 樹形結構肯定能想到樹形dp,全樹對某點產生的貢獻一般可以通過一到兩遍樹形dp計算得出,本題所求期望等於每個元件被充電的概率之和。設f i 表示i被充電的...
bzoj3566 SHOI2014 概率充電器
n個充電器連成一棵樹。第i個充電器有p i 的概率直接充電。每條導線有一定機率可以導電。可以導電的導線形成的聯通塊中只要存在直接充電的結點整個聯通塊的充電器均進入充電狀態。問期望進入充電狀態的充電器個數 顯然可知我們只需要得到f i 表示i進入充電狀態的概率 那麼a ns f i 我們把無根樹變有根...
BZOJ 4597 Shoi2016 隨機序列
很可做的一道題 考慮一下一段序列的答案為b x,x為最右連續一段是乘積,然後和為x,b則為對應的左邊的和 然後考慮在右邊加乙個數k,分類討論一下發現x kx,b 2x 3b 於是就可以dp了 然後dp可以矩陣轉移 於是就可以用線段樹維護矩陣 就水過去了 好像很簡單哎,ac率好高的說 include ...