0

I am implementing graph algorithm on Hackerrank.
Problem statement :
The Ruler of HackerLand believes that every citizen of the country should have access to a library. Unfortunately, HackerLand was hit by a tornado that destroyed all of its libraries and obstructed its roads! As you are the greatest programmer of HackerLand, the ruler wants your help to repair the roads and build some new libraries efficiently.
HackerLand has n cities numbered from 1 to n. The cities are connected by m bidirectional roads. A citizen has access to a library if:

  1. Their city contains a library.
  2. They can travel by road from their city to a city containing a library.

The following figure is a sample map of HackerLand where the dotted lines denote obstructed roads:

Test case
The cost of repairing any road is c_road dollars, and the cost to build a library in any city is c_lib dollars. If in the above example c_road=2 and c_lib=3 , we would build 5 roads at a cost of 5*2 and 2 libraries for a cost of 6 . We don't need to rebuild one of the roads in the cycle 1->2->3->1.
You are given q queries, where each query consists of a map of HackerLand and value of c_lib and c_road . For each query, find the minimum cost of making libraries accessible to all the citizens and print it on a new line.

My approach :
I make a graph with the given cities and roads, where each city denotes a node in the graph and each road denotes a edge. I used BFS algorithm to find connected components of the graph. Then make a library in each component, and build minimum number of roads so that components remains connected.


Answer :
Rerurn the minimum of two.

  1. The cost of making a library in each component + repairing roads so that each component has minimum number of roads.
  2. Making a library in each city.
    In the above case cost of building a road is 2 dollars (c_road=2) and cost of making a library is 3 (c_lib=3).


    Here, this graph has two components:
  3. 1,2,3,7 (road required is 3)
  4. 5,6,8 (road required is 2)

Cost of making a library in each component(2*3=6) + cost of buiding required road is (5*2=10) = 16
Cost of building a library in each node is (7*3=21)=21
So, 16 is the answer.

My Code :
Note : 1 based indexing of graph used in this program.

#include<bits/stdc++.h>
using namespace std;

class Graph{
    int v; // number of vertices
    vector<int>*adj;
    public:

        Graph(int V){
            this->v=V+1;
            this->adj=new vector<int>[this->v];
        }

        void addEdge(int u,int v,bool biDir=true){
            adj[u].push_back(v);
            if(biDir)
                adj[v].push_back(u);
        }

        void bfs(int ar[]){
             // create a array of boolean to keep track of visited nodes.
             int numComponent=0,numEdge=0;
            bool visited[this->v];
            for(int i=1;i<this->v;i++)
                visited[i]=false;
            // for each node in graph
            for(int i=1;i<this->v;i++){
                if(!visited[i]){
                    numComponent++;
                    numEdge+=bfsUtill(i,visited);
                }

            }
            ar[0]=numComponent;
            ar[1]=numEdge;
        }

        int bfsUtill(int src, bool visited[]){
            // make a queue and insert src into it
            int numEdge=0;
            queue<int>q;
            q.push(src); // insert src into queue
            // mark first node as visited
            visited[src]=true;
            while(!q.empty()){
                int node=q.front();
                // visit
                cout<<node<<" ";
                // remove this node from queue
                q.pop(); 
                // visit every node adjacent to node 'node' 
                // if that node not visited then visit and enque it.
                for(int adjNode:adj[node]){
                    if(!visited[adjNode]){
                        numEdge++;
                        visited[adjNode]=true;
                        q.push(adjNode);
                    }
                }
            }
            return numEdge;
        }
};

// Complete the roadsAndLibraries function below.

long roadsAndLibraries(int n, int c_lib, int c_road, vector<vector<int>> cities) {
// if c_road is greater than c_lib then
if (c_road>c_lib){
    return n*c_lib;
}
Graph g(n);
// make graph of given vertices
for(auto x:cities)
    g.addEdge(x[0],x[1]);

// Array to store number of component and number of edges need to be repaired
int ar[2];
g.bfs(ar); 

long long int  libInEach=n*c_lib;
long long int roadAlso= ar[0]*c_lib+(ar[1]*c_road);

return min(libInEach,roadAlso);
}
// driver code
int main(){
    int t,n,m,c_lib,c_road;
    vector<vector<int>>cities;
    vector<int>temp;
    cin>>t;
    while(t--){
        cin>>n,m,c_lib,c_road;
        int a,b;
        for(int i=0;i<m;i++){
            cin>>a>>b;
            temp.push_back(a,b);
            cities.push_back(temp);
            temp.erase();
        }
        cout<<roadsAndLibraries(n,c_lib,c_road,cities);
    }
    return 0;
}

I am getting correct answer for some test cases and incorrect for some test cases.
I posted only required code, insted of whole program. Input is passed into this function roadsAndLibraries() .
I test helper function and those are working fine.

-bfs()
- bfsUtill()
Test cases :

2
3 3 2 1
1 2
3 1
2 3
6 6 2 5
1 3
3 4
2 4
1 2
2 3
5 

Output for this test case :

4
12
  • you need to write more tests to find one that fails, then you can fix it. If you want help, you need to include a [mcve]. (you didnt ask a question btw) – 463035818_is_not_an_ai Apr 21 '20 at 12:12
  • @idclev463035818 - you are right, but this guy already included [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Rahul Apr 21 '20 at 12:25
  • @Rahul not kniowing what input causes wrong output means it is not reproducible. Unless someone is lucky to spot the mistake in the code, it would be required to find such input and calculate the correct output by some other means eg by hand. This is something OP could have done – 463035818_is_not_an_ai Apr 21 '20 at 12:31
  • @Rahul from the link "Complete – Provide all parts someone else needs to reproduce your problem in the question itself" and "Reproducible – Test the code you're about to provide to make sure it reproduces the problem" neither is possible without the input that produces wrong output. I am not trying to say that this question is crap, but I am trying to say that first step of finding the answer must be finding a test that fails – 463035818_is_not_an_ai Apr 21 '20 at 12:35
  • @idclev463035818I'd - as you said, i included main function and some test cases. –  Apr 21 '20 at 13:21

1 Answers1

1

I edited your code. This might work for your test cases on hackerrank. This is working fine on given test cases. In any component if totel number of vertices is n then minimum number of edges, that can represent the same connected component is n-1.

#include<bits/stdc++.h>
using namespace std;

class Graph{
    int v; // number of vertices
    vector<int>*adj;
    public:

        Graph(int V){
            this->v=V+1;
            this->adj=new vector<int>[this->v];
        }

        void addEdge(int u,int v,bool biDir=true){
            adj[u].push_back(v);
            if(biDir)
                adj[v].push_back(u);
        }

        void bfs(int ar[]){
             // create a array of boolean to keep track of visited nodes.
             int numComponent=0,numEdge=0;
            bool visited[this->v];
            for(int i=1;i<this->v;i++)
                visited[i]=false;
            // for each node in graph
            for(int i=1;i<this->v;i++){
                if(!visited[i]){
                    numComponent++;
                    numEdge+=bfsUtill(i,visited);
                }

            }
            ar[0]=numComponent;
            ar[1]=numEdge;
        }

        int bfsUtill(int src, bool visited[]){
            // make a queue and insert src into it
            int numEdge=1;
            queue<int>q;
            q.push(src); // insert src into queue
            // mark first node as visited
            visited[src]=true;
            while(!q.empty()){
                int node=q.front();
                // visit
                cout<<node<<" ";
                // remove this node from queue
                q.pop(); 
                // visit every node adjacent to node 'node' 
                // if that node not visited then visit and enque it.
                for(int adjNode:adj[node]){
                    if(!visited[adjNode]){
                        numEdge++;
                        visited[adjNode]=true;
                        q.push(adjNode);
                    }
                }
            }
            return numEdge-1;
        }
};

// Complete the roadsAndLibraries function below.

long roadsAndLibraries(int n, int c_lib, int c_road, vector<vector<int>> cities) {
// if c_road is greater than c_lib then
if (c_road>c_lib){
    return n*c_lib;
}
Graph g(n);
// make graph of given vertices
for(auto x:cities)
    g.addEdge(x[0],x[1]);

// Array to store number of component and number of edges need to be repaired
int ar[2];
g.bfs(ar); 

long long int  libInEach=n*c_lib;
long long int roadAlso= ar[0]*c_lib+(ar[1]*c_road);

return min(libInEach,roadAlso);
}
// driver code
int main(){
    int t,n,m,c_lib,c_road;
    vector<vector<int>>cities;
    vector<int>temp;
    cin>>t;
    while(t--){
        cin>>n,m,c_lib,c_road;
        int a,b;
        for(int i=0;i<m;i++){
            cin>>a>>b;
            temp.push_back(a,b);
            cities.push_back(temp);
            temp.erase();
        }
        cout<<roadsAndLibraries(n,c_lib,c_road,cities);
    }
    return 0;
}
Rahul
  • 310
  • 2
  • 13