1

I have a task which I have been trying to solve for the last week. It's driving me crazy. The task is:

Given a node count N(1 <= N <= 10`000),

nonadjacent node pair count M(1 <= M <= 200`000)

and the nonadjacent node pairs themselves

M0A, M0B,

M1A, M1B,

...

MM-1A, MM-1B,

find the maximum clique.

I am currently trying all kinds of bron-kerbosch algorithm variations. But every time I get a time limit on the testing site. I posted the only code that doesn't have a time limit BUT it has a wrong answer. The code is kind of optimized by not creating a new set every recursion.

Anyways, PLEASE help me. I am a desperate latvian teen programmer. I know this problem can be solved, because many people have solved it on the testing site.

#include <set>
#include <vector>

std::map<int, std::set<int> > NotAdjacent;

unsigned int MaxCliqueSize = 0;

void PrintSet(std::set<int> &s){
    for(auto it = s.begin(); it!=s.end(); it++){
        printf("%d ",*it);
    }
    printf("\n");
}

void Check(std::set<int> &clique, std::set<int> &left){
    //printf("printing clique: \n");
    //PrintSet(clique);
    //printf("printing left: \n");
    //PrintSet(left);

    if(left.empty()){
        //PrintSet(clique);
        if(clique.size()>MaxCliqueSize){
            MaxCliqueSize = clique.size();
        }
        return;
    }


    while(left.empty()==false){
        std::vector<int> removed;

        int v = *left.begin();
        left.erase(left.begin());


        for(auto it2=NotAdjacent[v].begin();it2!=NotAdjacent[v].end();it2++){

            auto findResult = left.find(*it2);

            if(findResult!=left.end()){
                removed.push_back(*it2);
                left.erase(findResult);
            }

        }

        clique.insert(v);
        Check(clique, left);
        clique.erase(v);

        for(unsigned int i=0;i<removed.size();i++){
            left.insert(removed[i]);
        }

    }
}

int main(){
    int n, m;
    scanf("%d%d",&n,&m);

    int a, b;
    for(int i=0;i<m;i++){
        scanf("%d%d",&a,&b);
        NotAdjacent[a].insert(b);
        NotAdjacent[b].insert(a);
    }

    std::set<int> clique, left;

    for(int i=1;i<=n;i++){
        left.insert(i);
    }
    Check(clique, left);
    printf("%d",MaxCliqueSize);
}

  • Please try to avoid `using namespace std;` because it is considered bad practice. See [Why is “using namespace std;” considered bad practice?](https://stackoverflow.com/q/1452721) – L. F. Sep 07 '19 at 09:44
  • Okey, I understood. I will edit the code. – a_young_programmer Sep 07 '19 at 09:53
  • Can you please share a link to the problem on the testing website? – גלעד ברקן Sep 07 '19 at 13:31
  • https://clevercode.lv/task/show/mezu_ezi It's in Latvian, but you can translate it to english. Also you have to register in order to test your code. Thank you for helping me solve the previous problem. I remember you גלעד ברקן :p – a_young_programmer Sep 07 '19 at 13:37
  • It looks like you’re trying to use a pivot, but you don’t even have the three arguments for the original version of the algorithm. Is that intentional? – Davis Herring Sep 12 '19 at 04:07
  • I am trying to do the one without pivot. The thing is I realized that creating a new class every call is very time consuming, so I am trying to pass by redlference. But I now know that the code isn't correct at all. So you can just ignore the code. xd – a_young_programmer Sep 12 '19 at 04:12
  • It is simply not possible. The task that was given to me was incorrect cause there was a lot of information missing. The real task was just way too simple for me to bother posting it here. – a_young_programmer Oct 08 '19 at 21:00

1 Answers1

1

For what it's worth, this code seems to pass 5 tests and I think all the rest exceed either time or memory limits (submitted as C++11). This idea is to find a maximum independent set in the graph complement, for which we readily receive the edges for. The algorithm is what I could understand of the standard greedy one. Perhaps this can give you or others more ideas? I believe there are some improved algorithms for MIS.

#include <iostream>
using namespace std;

#include <map>
#include <set>
#include <vector>
#include <algorithm>

std::map<int, std::set<int> > NotAdjacent;
vector<int> Order;
unsigned int NumConnectedToAll = 0;
unsigned int MaxCliqueSize = 0;

bool sortbyN(int a, int b){ 
  return (NotAdjacent[a].size() > NotAdjacent[b].size());
}  

void mis(std::set<int> &g, unsigned int i, unsigned int size){
    if (g.empty() || i == Order.size()){
        if (size + NumConnectedToAll > MaxCliqueSize)
          MaxCliqueSize = size + NumConnectedToAll;
        return;
    }

    if (g.size() + size + NumConnectedToAll <= MaxCliqueSize)
     return;

    while (i < Order.size() && g.find(Order[i]) == g.end())
      i++;
    int v = Order[i];
    std::set<int> _g;
    _g = g;
    _g.erase(v);
    for (auto elem : NotAdjacent[v])
      _g.erase(elem);

    mis(_g, i + 1, size + 1);
}

int main(){
    int n, m;
    scanf("%d%d",&n,&m);

    int a, b;
    for(int i=0;i<m;i++){
        scanf("%d%d",&a,&b);
        NotAdjacent[a].insert(b);
        NotAdjacent[b].insert(a);
    }

    std::set<int> g;
    Order.reserve(NotAdjacent.size());
    for (auto const& imap: NotAdjacent){
      Order.push_back(imap.first);
      g.insert(imap.first);
    }
    sort(Order.begin(), Order.end(), sortbyN); 

    for (int i=1; i<=n; i++)
      if (NotAdjacent.find(i) == NotAdjacent.end())
        NumConnectedToAll++;

    for (unsigned int i=0; i<Order.size(); i++){
      mis(g, i, 0);
      g.erase(Order[i]);
    }

    printf ("%d", MaxCliqueSize);
    return 0;
}
גלעד ברקן
  • 23,602
  • 3
  • 25
  • 61
  • I will try that out tomorrow or later today. Sounds very promising. Thank you – a_young_programmer Sep 07 '19 at 15:01
  • While this does sound good. I can't seem to think of a way to get it faster than O(n^2). But I will keep on trying. :/ – a_young_programmer Sep 08 '19 at 08:24
  • In latvian there is a button called "Iesūtīt" right above the task, but you have to be logged in in order for it to show up. – a_young_programmer Sep 08 '19 at 10:16
  • I will check it out as soon as I get home. – a_young_programmer Sep 08 '19 at 11:15
  • @a_young_programmer I think my idea is `O(M log M)`, not `O(n^2)`. I added an explanation and procedure. – גלעד ברקן Sep 08 '19 at 15:02
  • I will need some time to wrap my head around this. Thank you for taking your time in order to help me. – a_young_programmer Sep 08 '19 at 15:50
  • Can you explain this: `what all vertices of any one clique have in common is the exact same set of non-adjacent vertices.` ? Let's note: `a/b` the fact that `a` is not adjacen to `b`. Then I can have 4 nodes, `a,b,c,d` with: `a/c`, `b/d`, `c/a`, `d/b` and a maximal clique made of `c` and `d` and yet they don't have the same non-adjacency list. – fjardon Sep 09 '19 at 13:51
  • @fjardon ah, good point. Maybe what I've proposed assumes the cliques are separate components? – גלעד ברקן Sep 09 '19 at 15:03
  • @גלעד ברקן Yeah, i was kinda wondering about that, but I thought I was understanding the answer the wrong way. Maybe we can kinda connect these components in some way. – a_young_programmer Sep 09 '19 at 15:18
  • This really is helpful, thank you. I will keep on trying. ( I'm leaving this message here for you to know that i haven't gave up yet and your effort wasn't for nothing ) :) – a_young_programmer Sep 13 '19 at 14:51
  • @a_young_programmer cool. By now I'm interested so I would not feel the effort is wasted even if you've moved on :) An optimisation might be to maintain a structure for `g` that lets us efficiently cull at once all the next nodes with neighbours with `order` greater than `i`, because all those are guaranteed *not* to be neighbours of the current MIS. But this kind of structure might need to be a custom implementation, requiring more work. – גלעד ברקן Sep 13 '19 at 15:45
  • It seems like i won't be able to figure it out by myself. I will try to ask my new teacher tomorrow, cause I entered a programming school recently. – a_young_programmer Sep 16 '19 at 14:17
  • @a_young_programmer great. Please post the idea when you find it out. – גלעד ברקן Sep 16 '19 at 14:21
  • @גלעדברקן My teacher hasn't attempted it yet, but one of his best students has solved it. He's a 13 year old world level programmer. We reached out to him and he agreed to try to explain the solution to the whole programming class. I don't know for sure when it will happen. I am estimating a month. – a_young_programmer Sep 17 '19 at 17:24