-2

I wanted to count the number of groups in an undirected graphs in c++.I was trying using bfs but was unsuccessful.I have been given a range of numbers [L,R] (or think of these ranges as number of vertices) and i have to find the number of groups.How do i do this?

Like if i have (Input):

1 3
2 5
6 9

Output:

2

As there are 2 groups.

My code:

bool visited[MAX];
vector<int> v[MAX];
int solve(int x)
{
  queue<int> q;int ans=0;
  q.push(x);
  if(v[x].empty())
  {
      ans++;
  }
  while(!q.empty())
  {
      int curr = q.front();
      visited[curr] = true;
      q.pop();
      for(int i = 0; i < v[curr].size(); i ++)
        {
            if(!visited[v[curr][i]])
            {
                q.push(v[curr][i]);
                visited[v[curr][i]] = true;
            }
        }
        if(v[curr].empty()) ans++;
  }
  return ans;
}
int main()
{
    int t;scanf("%d",&t);

    while(t--)
    {
        int l,r,n,ans=0,min_,max_=0;
        scanf("%d",&n);
        for(int i = 0; i < n; i ++)
            visited[i] = false;
        for(int j=0;j<n;j++)
        {
            scanf("%d",&l);scanf("%d",&r);
            for(int i=l;i<r;i++)
            {
                v[i].push_back(i+1);
                 min_ = min(min_,i);
                max_ = max(max_,i+1);
            }
        }

        printf("%d\n",solve(min_));
    }
    return 0;
}
wen_dy
  • 31
  • 7
  • "But it was unsuccessful". What did go wrong? Did your program crash? Did it produce incorrect output? – kraskevich Jan 06 '15 at 15:55
  • @user111 It seems like you have a different idea on how to define graphs. Typically they are defined by a bunch of `std::pair`s with each element of the pair representing a node. Your input is "1->3, 2->5, 6->9" and you say that will make "2" graphs? To be clear that should make **3 graphs**, you agree with that, right? – Jonathan Mee Jan 06 '15 at 16:35
  • @JonathanMee It will make graphs : 1->2->3->4->5 and 6->7->8->9 . So, 2 graphs. – wen_dy Jan 06 '15 at 17:29
  • @IloveCoding I got Runtime Error(SIGSEGV). I just need to know how do i count groups in an undirected graph. – wen_dy Jan 06 '15 at 17:31
  • @user111 How large can n, L and R be? – kraskevich Jan 06 '15 at 17:34
  • 1 ≤ N ≤ 10^5, 0 ≤ L ≤ R ≤ 2000 – wen_dy Jan 06 '15 at 17:38
  • You mean like [this](http://stackoverflow.com/questions/27745166/algorithms-used-to-find-the-overlaps-sets)? And [this](http://stackoverflow.com/questions/27753830/finding-minimum-number-of-points-which-covers-entire-set-of-intervals)? And this http://www.codechef.com/JAN15/problems/ONEKING? – beaker Jan 06 '15 at 18:16
  • 1
    @beaker They look different to me. This one is about finding the number of connected components, the last 2 links are about something like vertex cover. – kraskevich Jan 06 '15 at 18:31
  • @beaker The first is about finding the largest set of segments. The second two are about finding the minimum number of points which connect to all segments. This question is related but is about finding the number of disconnected segment sets. (And notably not at all about graphing.) – Jonathan Mee Jan 06 '15 at 19:18

2 Answers2

0

Let's take a look at how many edges are created in the worst case. It is N * (MAX_R - MIN_L), which is 10^5 * 2000 under given constraints. You program runs out of memory and gets runtime error. A more efficient algorithm is required. Here is a simple solution that uses only O(MAX_R) memory and
O(N + MAX_R) time.

vector<int> start(MAX_R + 1);
vector<int> end(MAX_R + 1);
int n;
cin >> n;
for (int i = 0; i < n; i++) {
    int low;
    int high;
    cin >> low >> high;
    start[low]++;
    end[high]++;
}
int res = 0;
int sum = 0;
for (int pos = 0; pos <= MAX_R; pos++) {
    if (sum == 0 && start[pos] > 0)
        res++;
    sum += start[pos] - end[pos];
}
cout << res << endl;

There is no need for bfs or any other graph algorithms in this problem.

You could fix your original solution by avoiding multiple edges in the graph(there is no need to create an edge from i to i + 1 if it already exists, but I am not sure if your original solution is correct).

kraskevich
  • 18,368
  • 4
  • 33
  • 45
0

Looks like you should start by changing to vector<pair<int,int>> v;. Then to populate v you should use:

scanf("%d", &l);scanf("%d", &r);
v.push_back(make_pair(l, r);

Then your function should become something like:

int solve(){
    vector<pair<int, int>> results;

    for(auto& vIndex : v){
        auto resultIndex = find_if(results.begin(), results.end(), [vIndex](const pair<int, int>& i){return vIndex.first >= i.first && vIndex.first <= i.second || vIndex.second >= i.first && vIndex.second <= i.second;});

        if(resultIndex == results.end()){
            results.push_back(vIndex);
        }else{
            resultIndex->first = min(vIndex.first, resultIndex->first);
            resultIndex->second = max(vIndex.second, resultIndex->second);
        }
    }
    return results.size();
}

You can see this in action here: http://ideone.com/MDQBOr Just hard code your desired inputs into v.

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • @user111 It's worth pointing out that what you are constructing is not a graph but an [segment tree](http://en.wikipedia.org/wiki/Segment_tree). My approach is brute force, if you needed to solve this quickly, using the tree described in the link would be a better approach. – Jonathan Mee Jan 06 '15 at 19:05