時間限制: 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...