File: netconnections.c - Tab length: 1 2 4 8 - Lines: on off - No wrap: on off

#include <stdio.h>
#include <stdlib.h>

struct  Config { unsigned int machine, network, next, size; };

#define setMachine(m, n, x) ({ struct Config* p = (m); p->network = (n); p->next = (x); })
#define setNetwork(n, m, s) ({ struct Config* p = (n); p->machine = (m); p->size = (s); })

void  exec_command (struct Config* configs, unsigned int m1, unsigned int m2, unsigned int* unique)
{
  struct Config*  machine;
  unsigned int  n1 = configs[m1 - 1].network, n2 = configs[m2 - 1].network;

  if (n1 == 0)
  {
    if (n2 != 0)
    {
      setMachine (&configs[m1 - 1], n2, configs[n2 - 1].machine);
      setNetwork (&configs[n2 - 1], m1, configs[n2 - 1].size + 1);
    }
    else if (m1 != m2)
    {
      setMachine (&configs[m1 - 1], (n1 = ++(*unique)), m2);
      setMachine (&configs[m2 - 1], n1, 0);
      setNetwork (&configs[n1 - 1], m1, 2);
    }
  }
  else if (n2 == 0)
  {
    setMachine (&configs[m2 - 1], n1, configs[n1 - 1].machine);
    setNetwork (&configs[n1 - 1], m2, configs[n1 - 1].size + 1);
  }
  else if (n1 != n2)
  {
    if (configs[n1 - 1].size > configs[n2 - 1].size)
      n1 ^= n2 ^= n1 ^= n2;

    for (machine = &configs[configs[n1 - 1].machine - 1]; machine->next; machine = &configs[machine->next - 1])
      machine->network = n2;

    setMachine (machine, n2, configs[n2 - 1].machine);
    setNetwork (&configs[n2 - 1], configs[n1 - 1].machine, configs[n2 - 1].size + configs[n1 - 1].size);
  }
}

int exec_query (const struct Config* configs, unsigned int m1, unsigned int m2)
{
  return configs[m1 - 1].network == 0 ? m1 == m2 : configs[m1 - 1].network == configs[m2 - 1].network;
}

char  read_char (char* buffer, unsigned int length, unsigned int* offset)
{
  while (*offset < length && buffer[*offset] <= ' ')
    ++(*offset);

  return *offset < length ? buffer[(*offset)++] : '\0';
}

unsigned int  read_uint (char* buffer, unsigned int length, unsigned int* offset)
{
  unsigned int  value = 0;

  for (; *offset < length && ((value == 0 && buffer[*offset] <= ' ') || (buffer[*offset] >= '0' && buffer[*offset] <= '9')); ++(*offset))
    value = (buffer[*offset] <= ' ') ? value : (value * 10 + buffer[*offset] - '0');

  return value;
}

int main (int argc, char* argv[])
{
  struct Config*  configs;
  FILE*     file = fopen (argv[1], "r");
  unsigned int  length, m1, offset = 0, unique = 0, query[2] = {0, 0};
  char*     buffer, type;

  length = !fseek (file, 0, SEEK_END) ? ftell (file) : 0;
  buffer = (char*)malloc (length * sizeof (*buffer));
  fseek (file, 0, SEEK_SET);
  fread (buffer, sizeof (*buffer), length, file);

  for (configs = (struct Config*)calloc (read_uint (buffer, length, &offset), sizeof (*configs)); (type = read_char (buffer, length, &offset)) != '\0'; )
  {
    m1 = read_uint (buffer, length, &offset);

    if (type == 'c')
      exec_command (configs, m1, read_uint (buffer, length, &offset), &unique);
    else
      ++query[!exec_query (configs, m1, read_uint (buffer, length, &offset))];
  }

  printf ("%u,%u\n", query[0], query[1]);

  return 0;
}