forked from wisdompeak/LeetCode
-
Notifications
You must be signed in to change notification settings - Fork 1
[pull] master from wisdompeak:master #328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
File renamed without changes.
90 changes: 90 additions & 0 deletions
Tree/2277.Closest-Node-to-Path-in-Tree/2277.Closest-Node-to-Path-in-Tree_v2.cpp
This file contains hidden or 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
using ll = long long; | ||
const int MAXN = 100000; | ||
const int LOGN = 17; | ||
class Solution { | ||
public: | ||
vector<pair<int,int>> adj[MAXN]; | ||
int up[MAXN][LOGN+1]; | ||
int depth[MAXN]; | ||
ll distRoot[MAXN]; | ||
|
||
void dfs(int cur, int parent) | ||
{ | ||
up[cur][0] = parent; | ||
for(auto &[v,w]: adj[cur]) | ||
{ | ||
if(v == parent) continue; | ||
depth[v] = depth[cur] + 1; | ||
distRoot[v] = distRoot[cur] + w; | ||
dfs(v, cur); | ||
} | ||
} | ||
|
||
int lca(int a, int b) | ||
{ | ||
if(depth[a] < depth[b]) swap(a,b); | ||
int diff = depth[a] - depth[b]; | ||
for(int k = 0; k <= LOGN; k++){ | ||
if(diff & (1<<k)) a = up[a][k]; | ||
} | ||
if(a == b) return a; | ||
for(int k = LOGN; k >= 0; k--){ | ||
if(up[a][k] != up[b][k]){ | ||
a = up[a][k]; | ||
b = up[b][k]; | ||
} | ||
} | ||
return up[a][0]; | ||
} | ||
|
||
ll dist(int a, int b) | ||
{ | ||
int c = lca(a,b); | ||
return distRoot[a] + distRoot[b] - 2*distRoot[c]; | ||
} | ||
|
||
ll stepUp(int u, int k) { | ||
for (int i=LOGN; i>=0; i--) { | ||
if ((k>>i)&1) { | ||
u = up[u][i]; | ||
} | ||
} | ||
return u; | ||
} | ||
|
||
vector<int> closestNode(int n, vector<vector<int>>& edges, vector<vector<int>>& query) { | ||
for (auto& edge: edges) | ||
{ | ||
int u = edge[0], v = edge[1]; | ||
adj[u].push_back({v,1}); | ||
adj[v].push_back({u,1}); | ||
} | ||
|
||
depth[0] = 0; | ||
distRoot[0] = 0; | ||
dfs(0, 0); | ||
|
||
vector<int>rets; | ||
for(int k = 1; k <= LOGN; k++) { | ||
for(int v = 0; v < n; v++) { | ||
up[v][k] = up[up[v][k-1]][k-1]; | ||
} | ||
} | ||
|
||
for (auto&q: query) { | ||
int u = q[0], v = q[1], k = q[2]; | ||
vector<pair<int,int>>ans; | ||
int uv = lca(u,v); | ||
int uk = lca(u,k); | ||
int vk = lca(v,k); | ||
ans.push_back({depth[uv], uv}); | ||
ans.push_back({depth[uk], uk}); | ||
ans.push_back({depth[vk], vk}); | ||
sort(ans.rbegin(), ans.rend()); | ||
|
||
rets.push_back(ans[0].second); | ||
} | ||
|
||
return rets; | ||
} | ||
}; |
8 changes: 8 additions & 0 deletions
Tree/2277.Closest-Node-to-Path-in-Tree/Readme.md
This file contains hidden or 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,13 @@ | ||
### 2277.Closest-Node-to-Path-in-Tree | ||
|
||
#### 解法1:DFS | ||
|
||
本题的时间复杂度要求是o(N^2),所以常规解法是,从node开始dfs得到所有节点到node的距离dist2node。然后从start开始dfs整棵树,对于能够通往end的这个分支上的节点,取最小的dist2node。 | ||
|
||
本题还有一种比较精彩的解法。先遍历所有的点作为起点,dfs整棵树,这样得到全局的matrix[i][j]表示任意两点之间的距离。然后对于start,我们遍历它的邻居j,发现如果有```matrix[start][end]==matrix[j][end]+1```,说明j是位于从start到end的路径上。依次递归下去,就能直接从start走向end,沿途中取最小的matrix[j][node]. | ||
|
||
#### 解法2:LCA + Binary Lifting | ||
一个非常好用的结论:在一棵树里,w点到u->v路径最近的点,其实就是以下三个点里深度最大的那一个:lca(u,v), lca(u,w), lca(v,w) | ||
|
||
我们用binary lifting模板就可以很容易地得到这三个点的位置,取depth最大的那个即可。 | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.