題目描述:
a君住在魔法森林裡,魔法森林可以看做一棵n個結點的樹,結點從1~n編號。樹中的每個結點上都生長著蘑菇。蘑菇有許多不同的種類,但同乙個結點上的蘑菇都是同一種類,更具體地,i號結點上生長著種類為c[i]的蘑菇。
現在a君打算出去採蘑菇,但他並不知道**的蘑菇更好,因此他選定起點s後會等概率隨機選擇樹中的某個結點t作為終點,之後從s沿著(s,t)間的最短路徑走到t.並且a君會採摘途中所經過的所有結點上的蘑菇。
現在a君想知道,對於每乙個結點u,假如他從這個結點出發,他最後能採摘到的蘑菇種類數的期望是多少。為了方便,你告訴a君答案*n的值即可。
資料範圍:
30%的資料:n <= 2000
另有20%的資料:給出的第i條邊為
另有20%的資料:蘑菇的種類最多3種
100%的資料:1 <= n <= 3*10^5 , 0 <= c[i] <= n
這道題有虛數做法,有換根線段樹做法,也有點分治做法。
它們(除了虛樹,因為我並不會)都帶有乙隻log。雖然這道題時限比較寬鬆,但是有一位dalao想出了o(n)的做法。
我們隨便取乙個點為根。
定義一下:
s zx
sz_sz
x為以x
xx為根的子樹的大小,upx
up_up
x為從x
xx到根的路徑上,離x
xx最近的且顏色與x
xx相同的祖先的與x
xx在同一條路徑上的兒子。
假設我們做到節點u
uu,顏色為c
cc。考慮經過x
xx的路徑的貢獻。
黑色的節點表示與u同色的節點。
f
ff為離x
xx最近的且顏色與x
xx相同的祖先,x
xx為upu
up_up
u。假設以x
xx為根的子樹內的節點為起點,其它節點為終點,那麼很顯然以x
xx為根的子樹內每個節點都能接受到其它節點個數的貢獻,也就是n−s
zxn-sz_
n−szx
。同時另sum
xsum_
sumx
表示upup
up值為x
xx的節點,以它們為根的子樹大小的總和,貢獻加上sum
xsum_
sumx。
但是不難發現,這樣會算重。
以u
uu為例,它的子樹內,路徑上有顏色c
cc的貢獻應該至少來自u
uu。同理,它也沒有sum
xsum_
sumx
的貢獻。相當於這一次它們什麼貢獻都沒有獲得。
總結的來說,x
xx的子樹內,我們先全部加上n−s
zx+s
umxn-sz_+sum_
n−szx
+sum
x。同時對於u
uu及和它等概念的節點(例如它旁邊那個小黑),它們並沒有貢獻。但是為了方便,不操作等價於再減去n−s
zupu
+sum
upun-sz_}+sum_}
n−szup
u+
sumu
pu
。那麼還有一種情況,節點u
uu沒有upup
我們直接統計這類節點的,以它們為根的子樹大小,總和記為vvv。
那麼不屬於這些節點的點可以獲得v
vv的貢獻,屬於這些節點的點沒有獲得貢獻。
最後,因為沒有記以自己為起點的貢獻,所以都加上nnn。
對於所有的操作,在dfs
dfsdf
s序上,一次操作對應的點都是連續的,所以可以用差分來實現。時間複雜度o(n
)o(n)
o(n)
。最後再次膜拜蔡bir
dbir
dbirdbird
birdbi
rd,想出這個神仙做法。
並十分感謝z_y_s為我這個蒟蒻講解這個神仙演算法。
#include
#include
#include
using
namespace std;
const
int n=
3e5+
1000
;int n;
int c[n+1]
;vector<
int> e[n+1]
,e1[n+1]
,s[n+1]
;int siz[n+1]
,id[n+1]
,up[n+1]
,sum[n+1]
;void
dfs(
int u,
int fa)
sum[up[u]]+
=siz[u];}
int tree[n+1]
;void
update
(int a,
int b,
int c)
void
solve
(int u,
int fa)
}int num[n+1]
,ans[n+1]
;bool
cmp(
int x,
int y)
intmain()
dfs(1,
0),solve(1
,0);
for(
int i=
0;i<=n;i++
)for
(int i=
1;i<=n;i++
) ans[i]
=ans[i-1]
+tree[i]
;for
(int i=
1;i<=n;i++
)printf
("%d\n"
,ans[id[i]
]+n)
;return0;
}
z_y_sdalao的**qwq。 題解 P5058 ZJOI2004 嗅探器
題目鏈結 題目大意 給定乙個無向圖,求乙個編號最小的點 p 使得刪掉 p 後 s 和 t 不連通 tarjan 演算法 分析 首先我們要明確 點 p 一定是割點,因為只有你刪掉乙個點後圖不連通才有可能使得 s 和 t 不連通,然後我們可以用 tarjan 來做這個事情 常規求割點是什麼,時間戳 df...
P5058 ZJOI2004 嗅探器 割點
一開始看到它的時候,想都沒想直接cv了割點的模板。結果是這樣的 再次讀題,發現是只用找u v路徑上的最小割點,改一下就a了 ac includeusing namespace std const int maxn 1e6 7 struct nodeedge 2 maxn inthead maxn c...
洛谷P5058 ZJOI2004 嗅探器
某軍搞資訊對抗實戰演習,紅軍成功地侵入了藍軍的內部網路,藍軍共有兩個資訊中心,紅軍計畫在某台中間伺服器上安裝乙個嗅探器,從而能夠偵聽到兩個資訊中心互相交換的所有資訊,但是藍軍的網路相當的龐大,資料報從乙個資訊中心傳到另乙個資訊中心可以不止有一條通路。現在需要你盡快地解決這個問題,應該把嗅探器安裝在哪...