- 以c为根的子树,其中的所有节点和c的距离比和0的距离少1
- 除此之外,所有其他的节点和c的距离比和0的距离多1
- 如果以c为根的子树size为s,那么c和其他节点的距离和dp[c] = dp[0] - s + N - s,N为总节点数
- 求每个子树size的话,也是树形dp的思路,对于当前节点root和其其节点c1, c2...,size[root] = 1 + sum(size[ci])
我们dfs两次,第一次求出所有子树的size和其他节点到0的距离。第二次求每个节点到其余节点的距离和。另外可以注意到的一点,如果带权的话方法是一样的,我们知道当前节点到每个子节点的边的长度,对递推方程稍加修改即可,例题可以参考Fermat Point in Graph。对时间复杂度O(N),空间复杂度O(N):
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Solution { | |
public: | |
vector<int> sumOfDistancesInTree(int N, vector<vector<int>>& edges) { | |
vector<unordered_set<int>> g(N); | |
for (const auto& e : edges) | |
{ | |
g[e[0]].insert(e[1]); | |
g[e[1]].insert(e[0]); | |
} | |
vector<int> sz(N, 0); | |
int totalDist = 0; | |
countSize(-1, 0, g, sz, totalDist, 0); | |
vector<int> res(N, 0); | |
getDist(N, -1, 0, totalDist, g, sz, res); | |
return res; | |
} | |
private: | |
void countSize(int from, int to, vector<unordered_set<int>>& g, vector<int>& sz, int& totalDist, int currDist) | |
{ | |
totalDist += currDist; | |
int currSize = 1; | |
for (const auto& adj : g[to]) | |
{ | |
if (adj != from) | |
{ | |
countSize(to, adj, g, sz, totalDist, currDist + 1); | |
currSize += sz[adj]; | |
} | |
} | |
sz[to] = currSize; | |
} | |
void getDist(int N, int from, int to, int currDist, vector<unordered_set<int>>& g, vector<int>& sz, vector<int>& res) | |
{ | |
res[to] = currDist; | |
for (const auto& adj : g[to]) | |
if (adj != from) | |
getDist(N, to, adj, currDist - sz[adj] + N - sz[adj], g, sz, res); | |
} | |
}; |
No comments:
Post a Comment