本文涉及知识点
C++DFS
C++图论
LeetCod2477. 到达首都的最少油耗
给你一棵 n 个节点的树(一个无向、连通、无环图),每个节点表示一个城市,编号从 0 到 n - 1 ,且恰好有 n - 1 条路。0 是首都。给你一个二维整数数组 roads ,其中 roads[i] = [ai, bi] ,表示城市 ai 和 bi 之间有一条 双向路 。
每个城市里有一个代表,他们都要去首都参加一个会议。
每座城市里有一辆车。给你一个整数 seats 表示每辆车里面座位的数目。
城市里的代表可以选择乘坐所在城市的车,或者乘坐其他城市的车。相邻城市之间一辆车的油耗是一升汽油。
请你返回到达首都最少需要多少升汽油。
示例 1:
输入:roads = [[0,1],[0,2],[0,3]], seats = 5
输出:3
解释:
- 代表 1 直接到达首都,消耗 1 升汽油。
- 代表 2 直接到达首都,消耗 1 升汽油。
- 代表 3 直接到达首都,消耗 1 升汽油。
最少消耗 3 升汽油。
示例 2:
输入:roads = [[3,1],[3,2],[1,0],[0,4],[0,5],[4,6]], seats = 2
输出:7
解释:
- 代表 2 到达城市 3 ,消耗 1 升汽油。
- 代表 2 和代表 3 一起到达城市 1 ,消耗 1 升汽油。
- 代表 2 和代表 3 一起到达首都,消耗 1 升汽油。
- 代表 1 直接到达首都,消耗 1 升汽油。
- 代表 5 直接到达首都,消耗 1 升汽油。
- 代表 6 到达城市 4 ,消耗 1 升汽油。
- 代表 4 和代表 6 一起到达首都,消耗 1 升汽油。
最少消耗 7 升汽油。
示例 3:
输入:roads = [], seats = 1
输出:0
解释:没有代表需要从别的城市到达首都。
提示:
1 <= n <= 105
roads.length == n - 1
roads[i].length == 2
0 <= ai, bi < n
ai != bi
roads 表示一棵合法的树。
1 <= seats <= 105
后序DFS
由于上下车没有消耗,则每到达一个城市都下车,重新上车。由于没有环,每条线路都是唯一的,以首都为根的树,子节点指向父节点。
每个城市 chilld 到 城市 par的人数,为child子树的节点数量。
DFS返回:子树的节点数i1,到子树节点需要的油量i2。
当前节点的耗油量: ∑ ( i 2 + i 1 / s e a t + ( 0 ! = i 1 \sum (i2 + i1/seat + (0!= i1%seat)) ∑(i2+i1/seat+(0!=i1
当前子树的节点数量: ∑ i 1 \sum i1 ∑i1+1
代码
核心代码
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:
long long minimumFuelCost(vector<vector<int>>& roads, int seats) {
auto neiBo = CNeiBo::Two(roads.size()+1, roads, false);
function < pair<int, long long>(int,int)> DFS = [&](int cur, int par) {
int i1 = 1;
long long i2 = 0;
for (const auto& next : neiBo[cur]) {
if (par == next) { continue; }
auto [j1, j2] = DFS(next, cur);
i1 += j1;
i2 += j2+(j1/seats+ (0 != (j1%seats)));
}
return make_pair(i1, i2);
};
auto [i1, i2] = DFS(0, -1);
return i2;
}
};
单元测试
vector<vector<int>> roads;
int seats;
TEST_METHOD(TestMethod11)
{
roads = { {0,1},{0,2},{0,3} }, seats = 5;
auto res = Solution().minimumFuelCost(roads, seats);
AssertEx(3LL, res);
}
TEST_METHOD(TestMethod12)
{
roads = { {3,1},{3,2},{1,0},{0,4},{0,5},{4,6} }, seats = 2;
auto res = Solution().minimumFuelCost(roads, seats);
AssertEx(7LL, res);
}
TEST_METHOD(TestMethod13)
{
roads = {}, seats = 1;
auto res = Solution().minimumFuelCost(roads, seats);
AssertEx(0LL, res);
}