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

2022-05-21 15:03:08 字數 1438 閱讀 9597

時間限制: 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×10^5,1≤c≤10^9\)。

樹形\(dp\)+邊記憶化。

每次以i為端點\(dfs\),同時記憶化從子樹中的一條邊開始的合法路徑的條數及總權值。

這樣每條邊(視為有向邊)最多訪問一次,總邊數為\(2*n-2\),所以複雜度看似為\(o(n)\)?

最後,因為從每個點開始都\(dfs\)了一遍,所以結果要除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 pairpii;

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

}

訓練賽B FZB(樹形DP)

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

記憶化搜尋 dp

例子 33 1132 3411 1先去找 1,1 的最長距離,很明顯為1 接著找 1,2 的最長距離,很明顯為1 接著找 1,3 的最長距離,為2 1,3 1 2 然後找 2,1 的最長距離,為2 2,1 1 1 然後是 2,2 的最長距離,如果沒有記憶化,那麼搜尋過程為 2,2 2 1 1 1 但...

樹形結構計數問題 記憶化搜尋

分析 這裡要求的是全部節點的距離和,可以定義子問題為 某乙個節點去掉它的某一條邊而形成的子樹中,該節點的距離和以及該子樹的節點數.只需要知道全部節點的該資訊,對每個節點就可以通過其臨界節點的該資訊得到這個節點的距離和.總的時間代價是o 2 n 1 o 2 n 1 o 2 n 1 的.相比於o n 2...