题目链接:https://leetcode.cn/problems/reachable-nodes-in-subdivided-graph/
题目大意:给出一个图,给出所有边及其细分情况edges[]
,在每个边中插入cnt_i
个细分点。给出移动最大步数maxMoves
,求从0
节点开始,在最大步数内,能够访问到的节点(包括原来的节点和细分节点)的数量。
思路:DFS做,到达一个原节点就减去一定步数,并将剩余步数传递,做下一步的DFS。如果步数不够,那么就记录从这个点到邻居点能够走的步数(也就是细分节点的数量)。最后将访问到的原节点和细分节点数相加。但开始时没考虑先算出到每个原节点的最短距离,而是单纯靠着步数去做,还有些测试点过不了。
单纯DFS代码
class Solution {
public:
vector<vector<int>> dis;
vector<vector<int>> mv;
vector<vector<int>> adj;
vector<bool> known;
void DFS(int last, int node, int move) {
// if (known[node])
// return;
known[node] = true;
if (move == 0)
return;
for (auto neb : adj[node]) {
if (neb != last) {
if (mv[node][neb] + mv[neb][node] < dis[node][neb]-1 || dis[node][neb] == 1) {
if (move >= dis[node][neb]) {
mv[node][neb] = dis[node][neb]-1;
DFS(node, neb, move - dis[node][neb]);
}
else
mv[node][neb] = max(mv[node][neb], move);
}
}
}
return;
}
int reachableNodes(vector<vector<int>>& edges, int maxMoves, int n) {
const int MAXD = 0x7FFFFFFF;
dis.resize(n, vector<int>(n, MAXD));
mv.resize(n, vector<int>(n, 0));
adj.resize(n, vector<int>(0));
known.resize(n, false);
for (auto e : edges) {
int u = e[0], v = e[1], cnt = e[2];
dis[u][v] = dis[v][u] = cnt+1;
adj[u].push_back(v);
adj[v].push_back(u);
}
DFS(-1, 0, maxMoves);
int ret = 0;
for (int i = 0; i < n; i++)
ret += known[i];
for (auto e : edges) {
int u = e[0], v = e[1], cnt = e[2];
if (mv[u][v] + mv[v][u] < dis[u][v])
ret += mv[u][v] + mv[v][u];
else
ret += dis[u][v]-1;
}
return ret;
}
};
题解基本上都是Dijkstra做,先得出从0
到所有原节点所需的最少步数,随后将能访问到的原节点和细分节点数加起来。
完整代码
class Solution {
public:
vector<int> dist;
vector<vector<pair<int, int>>> G;
void Dij(int start) {
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
pq.emplace(0, start);
while (!pq.empty()) {
auto [d, x] = pq.top();
pq.pop();
if (d > dist[x])
continue;
for (auto [neb, neb_d] : G[x]) {
int tmp_d = dist[x] + neb_d;
if (tmp_d < dist[neb]) {
dist[neb] = tmp_d;
pq.emplace(tmp_d, neb);
}
}
}
}
int reachableNodes(vector<vector<int>>& edges, int maxMoves, int n) {
const int MAXD = 0x7FFFFFFF;
G.resize(n);
dist.resize(n, MAXD);
for (auto e : edges) {
int u = e[0], v = e[1], cnt = e[2];
G[u].emplace_back(v, cnt+1);
G[v].emplace_back(u, cnt+1);
}
dist[0] = 0;
Dij(0);
int ret = 0;
for (auto d : dist) {
if (d <= maxMoves)
ret++;
}
for (auto e : edges) {
int u = e[0], v = e[1], cnt = e[2];
int u2v = max(maxMoves - dist[u], 0);
int v2u = max(maxMoves - dist[v], 0);
ret += min(v2u + u2v, cnt);
}
return ret;
}
};