01: #include <stdio.h>
02: #include <stdlib.h>
03:
04: struct Config { unsigned int machine, network, next, size; };
05:
06: #define setMachine(m, n, x) ({ struct Config* p = (m); p->network = (n); p->next = (x); })
07: #define setNetwork(n, m, s) ({ struct Config* p = (n); p->machine = (m); p->size = (s); })
08:
09: void exec_command (struct Config* configs, unsigned int m1, unsigned int m2, unsigned int* unique)
10: {
11: struct Config* machine;
12: unsigned int n1 = configs[m1 - 1].network, n2 = configs[m2 - 1].network;
13:
14: if (n1 == 0)
15: {
16: if (n2 != 0)
17: {
18: setMachine (&configs[m1 - 1], n2, configs[n2 - 1].machine);
19: setNetwork (&configs[n2 - 1], m1, configs[n2 - 1].size + 1);
20: }
21: else if (m1 != m2)
22: {
23: setMachine (&configs[m1 - 1], (n1 = ++(*unique)), m2);
24: setMachine (&configs[m2 - 1], n1, 0);
25: setNetwork (&configs[n1 - 1], m1, 2);
26: }
27: }
28: else if (n2 == 0)
29: {
30: setMachine (&configs[m2 - 1], n1, configs[n1 - 1].machine);
31: setNetwork (&configs[n1 - 1], m2, configs[n1 - 1].size + 1);
32: }
33: else if (n1 != n2)
34: {
35: if (configs[n1 - 1].size > configs[n2 - 1].size)
36: n1 ^= n2 ^= n1 ^= n2;
37:
38: for (machine = &configs[configs[n1 - 1].machine - 1]; machine->next; machine = &configs[machine->next - 1])
39: machine->network = n2;
40:
41: setMachine (machine, n2, configs[n2 - 1].machine);
42: setNetwork (&configs[n2 - 1], configs[n1 - 1].machine, configs[n2 - 1].size + configs[n1 - 1].size);
43: }
44: }
45:
46: int exec_query (const struct Config* configs, unsigned int m1, unsigned int m2)
47: {
48: return configs[m1 - 1].network == 0 ? m1 == m2 : configs[m1 - 1].network == configs[m2 - 1].network;
49: }
50:
51: char read_char (char* buffer, unsigned int length, unsigned int* offset)
52: {
53: while (*offset < length && buffer[*offset] <= ' ')
54: ++(*offset);
55:
56: return *offset < length ? buffer[(*offset)++] : '\0';
57: }
58:
59: unsigned int read_uint (char* buffer, unsigned int length, unsigned int* offset)
60: {
61: unsigned int value = 0;
62:
63: for (; *offset < length && ((value == 0 && buffer[*offset] <= ' ') || (buffer[*offset] >= '0' && buffer[*offset] <= '9')); ++(*offset))
64: value = (buffer[*offset] <= ' ') ? value : (value * 10 + buffer[*offset] - '0');
65:
66: return value;
67: }
68:
69: int main (int argc, char* argv[])
70: {
71: struct Config* configs;
72: FILE* file = fopen (argv[1], "r");
73: unsigned int length, m1, offset = 0, unique = 0, query[2] = {0, 0};
74: char* buffer, type;
75:
76: length = !fseek (file, 0, SEEK_END) ? ftell (file) : 0;
77: buffer = (char*)malloc (length * sizeof (*buffer));
78: fseek (file, 0, SEEK_SET);
79: fread (buffer, sizeof (*buffer), length, file);
80:
81: for (configs = (struct Config*)calloc (read_uint (buffer, length, &offset), sizeof (*configs)); (type = read_char (buffer, length, &offset)) != '\0'; )
82: {
83: m1 = read_uint (buffer, length, &offset);
84:
85: if (type == 'c')
86: exec_command (configs, m1, read_uint (buffer, length, &offset), &unique);
87: else
88: ++query[!exec_query (configs, m1, read_uint (buffer, length, &offset))];
89: }
90:
91: printf ("%u,%u\n", query[0], query[1]);
92:
93: return 0;
94: }