Submission #210230

#TimeUsernameProblemLanguageResultExecution timeMemory
210230mohamedsobhi777Evacuation plan (IZhO18_plan)C++14
100 / 100
1853 ms103464 KiB
#include<bits/stdc++.h> using namespace std ; const int N = 5e5 + 7 ; /* idea: break the problem into smaller subproblems we need a path from A to B, avoiding bad nodes as much as we can first we need to know for each node the closest bad node to it(let's call it C[node]) which can be done if we run a dijkstra from each bad node simultaneously now the problem turns to the following find a path from A to B such that the the min of C[x] for each node x on the path is maximum one possible way to do that is to process each node after sorting them decresingly by C[i] when processing a node, we mark it as good, and look for its good neighbours to link them to it using DSU after processing each node, the answer to query {u , v} such that u and v is in the same component is min of all C[i] of nodes processed so far, if they are not in the same component we continue processing other nodes, so it make sense that we look for the first time nodes {u , v} were in the same component, which is the same as their lca if we root the tree at the last node we conunter, so the answer to query {u , v} = C[lca(u , v)] of the DSU tree submission : https://oj.uz/submission/210229 */ int n , m , k , q ; vector<pair<int , int > > adj[N] ; vector<pair<int , int > > queries ; bool good[N] , viz[N]; int root ; vector<int> qrs[N] , tree[N]; // this is DSU struct DSU{ vector<int> fat ; void init(int n){ fat.resize(n + 1 ) ; for(int i = 0 ; i < n ; i++){ fat[i] = i ; } } int fin(int x){ return fat[x] = (fat[x]==x?x:fin(fat[x])) ; } void unio(int a, int b){ int aa = fin(a) ; int bb = fin(b) ; if(aa!=bb){ fat[aa] = bb ; } } } d1 , d2; //using dijkstra to calculate the closest bad node priority_queue<pair<int , int > > Q; int C[N]; void dijkstra(){ while(Q.size()){ int dst = -Q.top().first ; int node = Q.top().second ; Q.pop() ; for(auto u : adj[node]){ if(C[u.first]==-1 || dst + u.second < C[u.first]){ C[u.first] = dst + u.second ; Q.push({-C[u.first] , u.first}) ; } } } } // vector<pair<int , int > > node ; map<pair<int , int > , bool > mp ; map<pair<int , int > , int > sol ; void dfs_lca(int x , int p ){ viz[x] = 1 ; for(auto u : qrs[x]){ if(viz[u] && mp[{x ,u}]==0){ int lca = d2.fin(u) ; mp[{x , u}] = mp[{u , x}] = 1 ; sol[{x , u}] = sol[{u , x}] = C[lca] ; } } for(auto u : tree[x]){ if(u==p) continue ; dfs_lca(u ,x ) ; d2.unio(u , x) ; } } int main(){ memset(C , -1 , sizeof C) ; cin>>n >>m; for(int i = 0 ; i < m ; i++){ int a , b, c; cin>>a>>b>>c ; adj[a].push_back({b , c}) ; adj[b].push_back({a , c}) ; } //calculating the distance between each node to the nearest bad node cin>>k ; for(int i = 0 ; i <k ; i++){ int a ; cin>>a ; C[a] =0 ; Q.push({0 , a}) ; } dijkstra() ; // cin>>q ; for(int i = 0 ; i < q ; i++){ int a, b ; cin>>a>>b ; queries.push_back({a ,b }); qrs[a].push_back(b) ; qrs[b].push_back(a) ; } //sorting the nodes decresingly by C[i] for(int i = 1 ; i <=n ; i++){ node.push_back({-C[i] , i}) ; } sort(node.begin() , node.end()) ; //process each node, mark it as good, and link it to its good neighbours d1.init(N) ; for(auto u : node){ int nod = u.second ; int home = d1.fin(nod) ; good[nod] = 1 ; for(auto it : adj[nod]){ if(good[it.first]){ int fn = d1.fin(it.first) ; if(fn!=home){ if(C[fn] < C[home])d1.unio(home , fn) ; else d1.unio(fn , home) ; //make a tree of the dsu components tree[fn].push_back(home) ; tree[home].push_back(fn) ; } } } root = nod ; } //calculate the LCA for each query using DSU offline d2.init(N) ; dfs_lca(root , root) ; //printing the answer for(int i = 0 ; i < q ; i++){ cout<<sol[queries[i]]<<"\n"; } return 0 ; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...