訓練賽B FZB(樹形DP)

2021-10-04 21:55:06 字數 1896 閱讀 2366

時間限制: 1 sec 記憶體限制: 128 mb

hja有一棵n個點的樹,樹上每個點有點權,每條邊有顏色。

一條路徑的權值是這條路徑上所有點的點權和,一條合法的路徑需要滿足該路徑上任意相鄰的兩條邊顏色都不相同。

問這棵樹上所有合法路徑的權值和是多少。

第一行乙個數n。

接下來一行n個數代表每個點的權值。

接下來n−1行每行三個整數s,e,c,代表s到e之間有一條顏色為c的邊。

一行乙個整數代表答案。

樣例輸入

66 2 3 7 1 4

1 2 1

1 3 2

1 4 3

2 5 1

2 6 2

樣例輸出

134對於30%的資料,1≤n≤1000。

對於另外20%的資料,資料隨機。

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

對於100%的資料,1≤n

≤3×1

05,1

≤c≤1

09

1≤n≤3×10^5,1≤c≤10^9

1≤n≤3×

105,

1≤c≤

109。

樹形d pdp

dp+邊記憶化。

每次以i為端點dfs

dfsdf

s,同時記憶化從子樹中的一條邊開始的合法路徑的條數及總權值。

這樣每條邊(視為有向邊)最多訪問一次,總邊數為2∗n

−2

2*n-2

2∗n−

2,所以複雜度看似為o(n

)o(n)

o(n)

?最後,因為從每個點開始都dfs

dfsdf

s了一遍,所以結果要除2。

//#pragma gcc optimize(2)

//#pragma gcc optimize(3, "ofast", "inline")

#include

using namespace std;

typedef

long

long ll;

typedef

unsigned

long

long ull;

typedef pair<

int,

int> pii;

const

int n=

1e6+5;

const ll mod=

1e9+7;

const

double eps=

1e-5

;//const double pi=acos(-1);

#define ls p<<1

#define rs p<<1|1

int tot,nex[n]

,head[n]

,ver[n]

,col[n]

;ll a[n]

;void

add(

int u,

int v,

int w)

struct node;}

}vis[n]

;node dfs

(int u,

int fa,ll sum,

int e)

;for

(int i=head[u]

;i;i=nex[i]);

else;}

}return now;

}int

main()

for(

int i=

1;i<=n;i++

) ans+

=dfs

(i,0

,a[i],0

).sum;

cout<2

}

問題 B FZB(樹形DP 邊記憶化)

時間限制 1 sec 記憶體限制 128 mb hja有一棵n個點的樹,樹上每個點有點權,每條邊有顏色。一條路徑的權值是這條路徑上所有點的點權和,一條合法的路徑需要滿足該路徑上任意相鄰的兩條邊顏色都不相同。問這棵樹上所有合法路徑的權值和是多少。第一行乙個數n。接下來一行n個數代表每個點的權值。接下來...

訓練 9 13 訓練賽

a.hdu 6230 乙個合法的子串 s 3n 2 滿足條件即1 2n 1 為以n為回文中心的回文串,n 3n 2為以2n 1為中心的回文串。故我們可以通過尋找回文中心對,來判斷相應合法子串的個數。利用manacher求出每個位置的最長回文半徑,則若i,j滿足條件 i j 則應有 p i geqsl...

訓練賽 詠歎

安師大附中訓練題目 給定乙個1到n的排列a,對其進行氣泡排序 counter 0 while a不是公升序的 counter counter 1 for i 1 to n 1 if a i a i 1 then swap a i a i 1 endifend forend while那麼經過幾輪排序...