I am attempting to complete the "Journey to the Moon" problem described below:
There are N trained astronauts numbered from 0 to N-1. But those in charge of the mission did not receive information about the citizenship of each astronaut. The only information they have is that some particular pairs of astronauts belong to the same country.
Your task is to compute in how many ways they can pick a pair of astronauts belonging to different countries. Assume that you are provided enough pairs to let you identify the groups of astronauts even though you might not know their country directly. For instance, if 1,2,3 are astronauts from the same country; it is sufficient to mention that (1,2) and (2,3) are pairs of astronauts from the same country without providing information about a third pair (1,3). Print An integer that denotes the number of permissible ways to choose a pair of astronauts.
I believe I have implemented a messy solution. I want advice on two fronts:
How many a more gracefully implement the DFS algorithm in C++? The current format appears to be very messy and lines like:
for(long i=0; i<ei[ti].size(); ++i){ ci+= dfs(ei,vi,ei[ti][i]); // try each node in the adjacency list }
make my eyes bleed.
Why is my current implementation so slow? I have noticed that most other people opted for an adjacency matrix implemented as a single dimensional array as opposed to an adjacency list to store the graph. I suspect that the accesses to the the
std::map
might be the cause of the issue, but I haven't benchmarked the code to find out. I am curious as to whether there is an optimized map implementation that would better suite the purpose.I also suspect recursion might be the issue. I haven't figured out a way to implement tail recursion in this yet. I did try using "inline" to resolve the issue, but (as expected) it didn't actually help the overall speed.
Please feel free to criticize any my C++ style in this, I'm fairly rusty.
I fully expect someone to point out some condition where the thing loops forever rather than exiting. If that's the case I am still am interested in hearing people's outlook on 1, 2, and 3.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
map <long long,vector <long long>> e; //edges
//Count Nodes with DFS
long dfs(map <long long,vector<long long>> ei, vector <bool> &vi,long long ti){ //graph, visited, target
//if it's visited bail
//cout << "entering dfs with target " << ti << endl;
if(vi[ti] == true){
//cout << "revisit of " << ti << " prevented" << endl << endl;
return 0;
}else{
//cout << "vi[ti] of " << ti << " was false!" << endl;
}
vi[ti] = true;
long long ci =1;
for(long i=0; i<ei[ti].size(); ++i){
ci+= dfs(ei,vi,ei[ti][i]); // try each node in the adjacency list
}
//cout << "going to return ci of " << ci << endl;
return ci;
//Deal with singletons
}
int main() {
long long n,p,q,z;
cin >> n >> p;
vector<bool> v;
for(long i =0; i<n; i++){
v.push_back(false);
}//visited initialize false
//Initialize all them vectors.
for(long i =0; i<n; ++i){
vector <long long> tv;
e.insert(pair <long long, vector<long long>>(i,tv));
}
//cout << "survived init" << endl;
//Build adjacency matrix
while(p--){
cin >> q >> z;
e[q].push_back(z); //should work
e[z].push_back(q);
}
//cout << "survived adj matrix" << endl;
long long sum = 0;
long long as = 0;
for(long i =0; i<n; ++i){
//cout << "Trying " << i << " now" << endl;
if(v[i] == false){
//cout << "v[" << i << "]" << " should now be true" << endl;
long long t=0;
//Only go this far if we have not visited.
t = dfs(e,v,i); //sum = sum + (total nodes so far) * current node
//cout << "sum = " << " " << sum << " + (" << as << " * " << t << ")" << endl;
//Multiply
sum = sum + (as * t);
as += t;
}else{
//cout << "i of " << i << " was false" << endl;
}
}
//Profit
cout << sum;
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
return 0;
}