牛客 路徑計數機 (樹形dp 字首和)

2022-03-17 03:44:25 字數 2233 閱讀 9033

有一棵n個點的樹和兩個整數p, q,求滿足以下條件的四元組(a, b, c, d)的個數:

1.$1\leq a,b,c,d \leq n$

2.點a到點b的經過的邊數為p。

3.點c到點d的經過的邊數為q。

4.不存在乙個點,它既在點a到點b的路徑上,又在點c到點d的路徑上。

第一行三個整數n,p,q。

接下來n - 1行,每行兩個整數u, v,表示樹上存在乙個連線點u和點v的邊。

輸出乙個整數,表示答案。

示例1輸入

5 2 1

1 22 3

3 42 5輸出4

說明合法的四元組一共有:

(1, 5, 3, 4),

(1, 5, 4, 3),

(5, 1, 3 ,4),

(5, 1, 4, 3)。

示例2輸入

4 1 1

1 22 3

3 4輸出

8備註:

對於前20%的資料,n,p,q≤50。

對於前40%的資料,n,p,q≤200。

對於另外10%的資料,p = 2, q = 2。

對於另外10%的資料,樹是一條鏈。

對於另外10%的資料,樹隨機生成。

對於所有資料1≤n,p,q≤3000,1≤u,v≤n,保證給出的是一棵合法的樹。

分析我已經弱到連$n^2$列舉路徑都不會了

再一次求助master_yi

這個題只要理順了就挺好想的了(說得好像我想得出來似的。

由於不相交的情況不好求,所直接看相交的情況。

找規律可以發現,如果兩條路徑相交,其中必有一條路徑兩個端點的lca在另一條路徑上

所有可以列舉長度為p的路徑,減去在以這條路徑上的點為端點lca的長度為q的路徑

然後又列舉長度為q的路徑,減去在以這條路徑上的點為端點lca的長度為p的路徑

發現當路徑端點lca相同的情況被多算了一次,於是就加回來

那麼如何實現呢?

設sq[x],sp[x]分別表示以x為端點lca,長度為q和長度為p的路徑條數

列舉路徑是$n^2$的,如果不能優化的話,那麼我們現在需要的是快速求出一條路徑上的sq或sp和

現在要求的是一條路徑的和,乙個乙個找點肯定會t,所以可以預處理一些東西能讓我們能夠拼湊出答案

如果預處理從根到某個節點x上的路徑的sq之和與sp之和,記為ssq[x]與spp[x]

那麼以i,j為兩端點的路徑中sq和sp之和就為ssq[i]+ssq[j]-ssq[lca[i][j]]-ssq[fa[lca[i][j]]]與ssp[i]+ssp[j]-ssp[lca[i][j]]-ssp[fa[lca[i][j]]]

感覺有些與字首和類似。。。。。。

這樣就可以o(1)計算了,總的時間複雜度就為o(n^2)

跟master_yi幾乎一樣的code

#include#include

using

namespace

std;

const

int maxn=3005

;int

fa[maxn],dep[maxn],ori[maxn],f[maxn][maxn],lca[maxn][maxn];

int n,p,q,ecnt,sp,sq,v[maxn<<1],nx[maxn<<1

],sq[maxn],sp[maxn],vis[maxn],info[maxn];

int find(int x)

void add(int u1,int v1)

void dfs1(int x,int

fa) ori[x]=fa;sq+=sq[x];sp+=sp[x];

}void dfs2(int x,int f)

intmain()

if(len==p)ans-=sq[i]+sq[j]-sq[lca[i][j]]-sq[fa[lca[i][j]]];

if(len==q)ans-=sp[i]+sp[j]-sp[lca[i][j]]-sp[fa[lca[i][j]]];

}for(int i=1;i<=n;i++)

if(p==q)ans+=1ll*(sp[i]-sp[fa[i]])*(sq[i]-sq[fa[i]]-1)/2

;

else ans+=1ll*(sp[i]-sp[fa[i]])*(sq[i]-sq[fa[i]]);

printf(

"%lld\n

",p==q?ans<<3:ans<<2);}

黑白樹(牛客網 樹形dp)

題目描述 一棵n個點的有根樹,1號點為根,相鄰的兩個節點之間的距離為1。樹上每個節點i對應乙個值k i 每個點都有乙個顏色,初始的時候所有點都是白色的。你需要通過一系列操作使得最終每個點變成黑色。每次操作需要選擇乙個節點i,i必須是白色的,然後i到根的鏈上 包括節點i與根 所有與節點i距離小於k i...

牛客訓練,殺樹,樹形dp

一道樹形dp題,我剛開始想的是dp i j dp i j dp i j 表示i為根結點最長鏈的長度為j的最小代價,轉移的時候很複雜,最後還是沒寫出來 也有可能是寫炸了,但是這個狀態應該也是可以的 比賽結束後看到題解是用dp i j dp i j dp i j 表示i為根結點最長鏈的長度小於等於j的最...

牛客網 黑白樹(樹形dp)

一棵n個點的有根樹,1號點為根,相鄰的兩個節點之間的距離為1。樹上每個節點i對應乙個值k i 每個點都有乙個顏色,初始的時候所有點都是白色的。你需要通過一系列操作使得最終每個點變成黑色。每次操作需要選擇乙個節點i,i必須是白色的,然後i到根的鏈上 包括節點i與根 所有與節點i距離小於k i 的點都會...