Emergency Phone 112
National Olympiad — Regional round
Submission name: no112C.cpp
Problem summary
Only M undirected roads remain usable between N settlements. For each query X Y, determine whether travel between X and Y is possible using the usable roads.
Input
N M; M road pairs; Q; then Q query pairs.
Output
One string of Q bits: 1 for reachable and 0 for unreachable, in query order.
Constraints
2 ≤ N ≤ 1000; 1 ≤ M ≤ 2N; 1 ≤ Q ≤ 100,000.
Worked example
An independently prepared example for this explanation.
Input
5 3 1 2 2 3 4 5 4 1 3 1 5 4 5 2 2
Output
1011
Solution analysis
- Running a traversal for every call repeats work. Instead label all connected components once.
- Start an iterative DFS at each still-unlabeled vertex and give all reachable vertices the same component number.
- For a query, compare the two labels.
- Vertices in the same component can reach each other; different components cannot.
Why it works
The connected-component labels partition the undirected graph into its maximal reachable sets. Equality of labels is therefore equivalent to the existence of a path.
Watch out. Output bits consecutively, not YES/NO or one answer per line. A settlement can always reach itself.
Commented C++17 solution
An independently written complete program with standard headers.
// Key idea: The connected-component labels partition the undirected graph into its maximal reachable
// sets. Equality of labels is therefore equivalent to the existence of a path.
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n,m;
cin>>n>>m;
vector<vector<int>>g(n+1);
for(int i=0;i<m;++i){
int a,b;
cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
vector<int>component(n+1,-1);
int count=0;
for(int s=1;s<=n;++s){
if(component[s]==-1){
stack<int>st;
st.push(s);
component[s]=count;
while(!st.empty()){
int v=st.top();
st.pop();
for(int u:g[v]){
if(component[u]==-1){
component[u]=count;
st.push(u);
}
}
}
++count;
}
}
int q;
cin>>q;
while(q--){
int a,b;
cin>>a>>b;
cout<<(component[a]==component[b]?'1':'0');
}
cout<<'\n';
}