本文涉及知识点
C++图论C++DFS
LeetCode1443. 收集树上所有苹果的最少时间
给你一棵有 n 个节点的无向树,节点编号为 0 到 n-1 ,它们中有一些节点有苹果。通过树上的一条边,需要花费 1 秒钟。你从 节点 0 出发,请你返回最少需要多少秒,可以收集到所有苹果,并回到节点 0 。
无向树的边由 edges 给出,其中 edges[i] = [fromi, toi] ,表示有一条边连接 from 和 toi 。除此以外,还有一个布尔数组 hasApple ,其中 hasApple[i] = true 代表节点 i 有一个苹果,否则,节点 i 没有苹果。
示例 1:
输入:n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,true,false,true,true,false]
输出:8
解释:上图展示了给定的树,其中红色节点表示有苹果。一个能收集到所有苹果的最优方案由绿色箭头表示。
示例 2:
输入:n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,true,false,false,true,false]
输出:6
解释:上图展示了给定的树,其中红色节点表示有苹果。一个能收集到所有苹果的最优方案由绿色箭头表示。
示例 3:
输入:n = 7, edges = [[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple = [false,false,false,false,false,false,false]
输出:0
提示:
1 <= n <= 105
edges.length == n - 1
edges[i].length == 2
0 <= ai < bi <= n - 1
hasApple.length == n
后序DFS
DFS(cur) 返回 是否有苹果,收集所有的苹果需要的时间。
由于是树(连通、无环图),故只有一个父节点,用父节点除重。
如果子树没有苹果无需访问。 否则总时间:2 + 子树需要的时间。
代码
核心代码
class CNeiBo
{
public:
static vector<vector<int>> Two(int n, vector<vector<int>>& edges, bool bDirect, int iBase = 0)
{
vector<vector<int>> vNeiBo(n);
for (const auto& v : edges)
{
vNeiBo[v[0] - iBase].emplace_back(v[1] - iBase);
if (!bDirect)
{
vNeiBo[v[1] - iBase].emplace_back(v[0] - iBase);
}
}
return vNeiBo;
}
static vector<vector<std::pair<int, int>>> Three(int n, vector<vector<int>>& edges, bool bDirect, int iBase = 0)
{
vector<vector<std::pair<int, int>>> vNeiBo(n);
for (const auto& v : edges)
{
vNeiBo[v[0] - iBase].emplace_back(v[1] - iBase, v[2]);
if (!bDirect)
{
vNeiBo[v[1] - iBase].emplace_back(v[0] - iBase, v[2]);
}
}
return vNeiBo;
}
static vector<vector<int>> Mat(vector<vector<int>>& neiBoMat)
{
vector<vector<int>> neiBo(neiBoMat.size());
for (int i = 0; i < neiBoMat.size(); i++)
{
for (int j = i + 1; j < neiBoMat.size(); j++)
{
if (neiBoMat[i][j])
{
neiBo[i].emplace_back(j);
neiBo[j].emplace_back(i);
}
}
}
return neiBo;
}
};
class Solution {
public:
int minTime(int n, vector<vector<int>>& edges, vector<bool>& hasApple) {
auto neiBo = CNeiBo::Two(n, edges, false, 0);
function<pair<bool, int>(int, int)> DFS = [&](int cur, int par) {
int time = 0;
bool bHas = hasApple[cur];
for (const auto& next : neiBo[cur]) {
if (par == next) { continue; }
auto [b, t] = DFS(next, cur);
if (!b) { continue; }
time += 2 + t;
bHas = true;
}
return make_pair( bHas,time );
};
auto [tmp,ans] = DFS(0, -1);
return ans;
}
};
单元测试
int n;
vector<vector<int>> edges;
vector<bool> hasApple;
TEST_METHOD(TestMethod11)
{
n = 7, edges = { {0,1},{0,2},{1,4},{1,5},{2,3},{2,6} }, hasApple = { false,false,true,false,true,true,false };
auto res = Solution().minTime(n, edges, hasApple);
AssertEx(8, res);
}
TEST_METHOD(TestMethod12)
{
n = 7, edges = { {0,1},{0,2},{1,4},{1,5},{2,3},{2,6} }, hasApple = { false,false,true,false,false,true,false };
auto res = Solution().minTime(n, edges, hasApple);
AssertEx(6, res);
}
TEST_METHOD(TestMethod13)
{
n = 7, edges = { {0,1},{0,2},{1,4},{1,5},{2,3},{2,6} }, hasApple = { false,false,false,false,false,false,false };
auto res = Solution().minTime(n, edges, hasApple);
AssertEx(0, res);
}
测试环境
操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。