简体   繁体   中英

Generate all undirected graphs with n nodes

I'm trying to generate all the undirected graphs with n nodes, using recursive backtracking. I have to write their matrix (I don't know how is it called in english - in my language it would be adjacent matrix - is that right?) into a file.

For example:

input

3

output

8
0 0 0 
0 0 0 
0 0 0 

0 0 0 
0 0 1 
0 1 0 

0 0 1 
0 0 0 
1 0 0 

0 0 1 
0 0 1 
1 1 0 

0 1 0 
1 0 0 
0 0 0 

0 1 0 
1 0 1 
0 1 0 

0 1 1 
1 0 0 
1 0 0 

0 1 1 
1 0 1 
1 1 0 

Here is my program:

#include <iostream>
#include <fstream>

using namespace std;

ifstream f("gengraf.in");
ofstream g("gengraf.out");

int st[100], n, adiacenta[100][100], l=1;

void tipar(int k)
{
    for (int i = 1; i < k; i++)
    {
        for (int j = i+1; j < k; j++)
        {
            adiacenta[i][j] = adiacenta[j][i] = st[l];
        }
        l++;
    }
    for (int i = 1; i < k; i++)
    {
        for (int j = 1; j < k; j++)
        {
            g << adiacenta[i][j] << " ";
        }
        g << endl;
    }
}

int valid(int k)
{
    return 1;
}

void back(int k)
{
    if (k == ((n - 1) * n / 2) + 1)
    {
        l = 1;
        tipar(k);
        g << endl;
    }
    else
    {
        for (int i = 0; i <= 1; i++)
        {
            st[k] = i;
            if (valid(k))
            {
                back(k + 1);
            }
        }
    }
}

int main()
{
    f >> n;
    g << pow(2, (n * (n - 1))/2);
    g << endl;
    back(1);
}

but my output is:

8
0 0 0 
0 0 0 
0 0 0 

0 0 0 
0 0 0 
0 0 0 

0 0 0 
0 0 1 
0 1 0 

0 0 0 
0 0 1 
0 1 0 

0 1 1 
1 0 0 
1 0 0 

0 1 1 
1 0 0 
1 0 0 

0 1 1 
1 0 1 
1 1 0 

0 1 1 
1 0 1 
1 1 0 

and I don't know how to fix that.

I see why does happen - I generate 2^(n*(n-1))/2) graphs (because that's how many undirected graphs with n nodes are), and instead of generating 8 distinct ones, I get only 4 distinct ones, shown 2 times.

That is (I suppose) because my program outputs a graph with, let's say, a link between the node 1 and 3 and another graph with a link between the node 3 and 1. And that is basically the same undirected graph.

So if I am right, I should make my program not show each graph twice and it should work. So basically I have to get rid of each graph with the "reversed" node (so if I got one with a link between 1 and 3, I shouldn't get another one with a link between 3 and 1 because they are the same).

Am I right?

If so, how can I do that?

Thanks.

Problems with your code:

  • Value of l in tipar() id not increased after assignment.
  • Size of adjacency matrix is n * n not k * k.

This code work as expected.

#include <iostream>
#include <fstream>

using namespace std;

ifstream f("gengraf.in");
ofstream g("gengraf.out");

int st[100], n, adiacenta[100][100], l=1;

int pow(int a, int b) {
    int r = 1;
    while (b) {
    if (b&1) r *= a;
    b >>= 1;
    a *= a;
    }
    return r;
}

void tipar()
{
    for (int i = 1; i <= n; i++)
    {
        for (int j = i+1; j <= n; j++)
        {
            adiacenta[i][j] = adiacenta[j][i] = st[l];
            l++;
        }
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            g << adiacenta[i][j] << " ";
        }
        g << endl;
    }
}

int valid(int k)
{
    return 1;
}

void back(int k)
{
    if (k == (n * (n-1) / 2) + 1)
    {
        l = 1;
        tipar();
        g << endl;
    }
    else
    {
        for (int i = 0; i <= 1; i++)
        {
            st[k] = i;
            if (valid(k))
            {
                back(k+1);
            }
        }
    }
}

int main()
{
    cin >> n;
    g << pow(2, (n * (n - 1))/2);
    g << endl;
    back(1);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM