#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;
}