-
Notifications
You must be signed in to change notification settings - Fork 157
Add English tutorial for LOJ-1101 – A Secret Mission #522
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
Open
sadat2103108
wants to merge
4
commits into
lightoj-dev:main
Choose a base branch
from
sadat2103108:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,236 @@ | ||
| # LightOJ 1101 – A Secret Mission | ||
|
|
||
| ## Problem Summary | ||
|
|
||
| We are given a connected weighted graph with (N) cities and (M) roads. | ||
| Each road has a *danger value*. | ||
|
|
||
| For each query (s, t), we must find a path from (s) to (t) such that: | ||
|
|
||
| > the maximum danger of any road on the path is minimized. | ||
|
|
||
| This is known as a **minimax path problem**. | ||
|
|
||
| --- | ||
|
|
||
| ## Key Observation | ||
|
|
||
| If we build a **Minimum Spanning Tree (MST)** of the graph, then: | ||
|
|
||
| > For any two nodes, the path between them in the MST minimizes the maximum edge weight among all possible paths in the original graph. | ||
|
|
||
| This is a well-known property of MSTs. | ||
|
sadat2103108 marked this conversation as resolved.
Outdated
|
||
| Therefore, once we construct the MST, we only need to answer queries on that tree. | ||
|
|
||
| --- | ||
|
|
||
| ## Strategy | ||
|
|
||
| 1. Build the MST using **Prim’s algorithm** | ||
| 2. Convert the graph into a tree | ||
| 3. Preprocess the tree using **Binary Lifting** | ||
| 4. Store: | ||
|
|
||
| * `anc[u][i]` → (2^i)-th ancestor of node (u) | ||
| * `mx[u][i]` → maximum edge weight from (u) to its (2^i)-th ancestor | ||
| 5. For each query: | ||
|
|
||
| * compute LCA of (u) and (v) | ||
| * find maximum edge on path (u to LCA) and (v to LCA) using binary lifting | ||
| * answer = max of the two above values. | ||
|
|
||
| --- | ||
|
|
||
| ## Complexity | ||
|
|
||
| * MST construction: (O(M log N)) | ||
| * Binary lifting preprocessing: (O(N log N)) | ||
| * Each query: (O(log N)) | ||
|
sadat2103108 marked this conversation as resolved.
Outdated
|
||
|
|
||
| This easily fits within constraints. | ||
|
|
||
| --- | ||
|
|
||
| ## Implementation | ||
|
|
||
| ```cpp | ||
| #include<bits/stdc++.h> | ||
| using namespace std; | ||
| #define br cout<<"\n"; | ||
| #define ll long long | ||
| #define loop(n) for(int i=0; i<(n); i++) | ||
| #define fr(i,init, n) for(int i=(init); i<(n); i++) | ||
| #define revl(i,init) for(int i=(init-1); i>=0; i--) | ||
| #define pb push_back | ||
| #define all(v) v.begin(),v.end() | ||
| #define nl "\n" | ||
|
sadat2103108 marked this conversation as resolved.
Outdated
|
||
|
|
||
|
|
||
| const int N = 50005, LOG=18 ; | ||
| vector<pair<int,int>> adj2[N], adj[N]; | ||
|
sadat2103108 marked this conversation as resolved.
Outdated
|
||
| bool vis[N]; | ||
| int anc[N][LOG], mx[N][LOG], dep[N]; | ||
|
|
||
|
|
||
| // clear global variables for each test case | ||
| void clear(){ | ||
| loop(N){ | ||
| vis[i] = false; | ||
| adj2[i].clear(); | ||
| adj[i].clear(); | ||
| } | ||
| memset(anc,0, sizeof(anc)); | ||
| memset(mx, 0, sizeof(mx)); | ||
| memset(dep, 0, sizeof(dep)); | ||
|
sadat2103108 marked this conversation as resolved.
|
||
| } | ||
|
|
||
| // create the MST from adj2[] and build the new one in adj[] | ||
|
sadat2103108 marked this conversation as resolved.
Outdated
|
||
| void createMST(){ | ||
|
|
||
| priority_queue< | ||
| tuple<int,int,int>, | ||
| vector<tuple<int,int,int>>, | ||
| greater<tuple<int,int,int>> | ||
| > pq; | ||
|
|
||
| pq.push({-1, 1,0}); | ||
|
sadat2103108 marked this conversation as resolved.
Outdated
|
||
|
|
||
| while(! pq.empty()){ | ||
| int wt, node, parent; | ||
| tie(wt, node, parent) = pq.top(); | ||
| pq.pop(); | ||
|
|
||
| if(vis[node]) continue; | ||
|
|
||
| vis[node] = true; | ||
|
|
||
| if(parent!=0){ | ||
| adj[parent].pb({node,wt}); | ||
| adj[node].pb({parent,wt}); | ||
| } | ||
|
|
||
|
|
||
| for(auto child: adj2[node]){ | ||
| if(!vis[child.first]){ | ||
| pq.push({child.second, child.first, node}); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| } | ||
|
|
||
| // dfs for binary-lifting precomputations | ||
| void dfs(int node, int par=0, int wt=0){ | ||
|
|
||
| dep[node] = dep[par]+1; | ||
| anc[node][0] = par; | ||
|
|
||
| mx[node][0]= wt; | ||
|
|
||
| fr(i,1,LOG){ | ||
| anc[node][i] = anc[ anc[node][i-1] ][i-1]; | ||
| mx[node][i] = max( mx[ anc[node][i-1] ][i-1] , mx[node][i-1] ); | ||
| } | ||
|
|
||
| for(auto child: adj[node]){ | ||
| if(child.first != par){ | ||
| dfs(child.first, node, child.second); | ||
| } | ||
|
sadat2103108 marked this conversation as resolved.
|
||
| } | ||
| } | ||
|
sadat2103108 marked this conversation as resolved.
Outdated
|
||
|
|
||
| int lca(int u, int v){ | ||
| if(dep[u]< dep[v]) swap(u,v); | ||
|
|
||
| revl(i,LOG){ | ||
| if( dep[ anc[u][i] ] >= dep[v] ){ | ||
| u = anc[u][i]; | ||
| } | ||
| } | ||
|
|
||
| if(u==v) return u; | ||
|
|
||
| revl(i,LOG){ | ||
| if(anc[u][i] != anc[v][i]){ | ||
| u = anc[u][i]; | ||
| v = anc[v][i]; | ||
| } | ||
| } | ||
|
|
||
| return anc[u][0]; | ||
|
|
||
| } | ||
|
|
||
| // maximum edge between a node and its ancestor | ||
| int maxedge(int node, int l){ | ||
| int dis = dep[node] - dep[l]; | ||
|
|
||
| int ans = 0; | ||
|
|
||
| revl(i,LOG){ | ||
| if(dis & (1<<i)){ | ||
| ans = max( ans, mx[node][i] ); | ||
| node= anc[node][i]; | ||
| } | ||
| } | ||
|
|
||
| return ans; | ||
|
|
||
| } | ||
|
sadat2103108 marked this conversation as resolved.
|
||
|
|
||
| int query(int u, int v){ | ||
|
|
||
| int l = lca(u,v); | ||
|
|
||
| return max( maxedge(u,l), maxedge(v,l) ); | ||
|
|
||
| } | ||
|
|
||
|
|
||
|
|
||
| int tc = 1; | ||
| void SOLVE(){ | ||
| clear(); | ||
| cout<<"Case "<<tc++<<":"<<nl; | ||
|
|
||
| int n,m; cin>>n>>m; | ||
| while(m--){ | ||
| int a,b,c; cin>>a>>b>>c; | ||
| adj2[a].pb({b,c}); | ||
| adj2[b].pb({a,c}); | ||
| } | ||
|
|
||
| createMST(); | ||
|
|
||
|
sadat2103108 marked this conversation as resolved.
|
||
| dfs(1); | ||
|
|
||
| int q; cin>>q; | ||
| while(q--){ | ||
| int u,v; cin>>u>>v; | ||
| cout<<query(u,v)<<nl; | ||
| } | ||
|
|
||
| } | ||
|
|
||
| signed main(){ | ||
| ios_base::sync_with_stdio(0); | ||
| cin.tie(0); | ||
| int t=1; | ||
|
|
||
| cin>>t;///////////////////// | ||
|
sadat2103108 marked this conversation as resolved.
Outdated
|
||
|
|
||
| while(t--) SOLVE(); | ||
| return 0; | ||
| } | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## References | ||
|
|
||
| * https://cp-algorithms.com/graph/mst_prim.html | ||
| * https://cp-algorithms.com/graph/lca_binary_lifting.html | ||
|
|
||
| --- | ||
|
|
||
| **Author:** Sadat | ||
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.