-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathadjmatrix.c
202 lines (153 loc) · 4.04 KB
/
adjmatrix.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* for memcpy */
#include <stdint.h> /* gives fixed sized ints */
#include <assert.h> /* basic failure reporting */
#include <error.h>
#define NODES 14098 /* compile time limit for fixed memory allocation */
#define MAXPEERS 32 /* compile time limit on max edges out of a node */
int32_t edges[NODES][MAXPEERS];
void read_edges();
int add_edge(int32_t, int32_t);
int add_peer(int32_t, int32_t (*)[], int);
void row_bfs(int32_t, int *);
int main(void) {
int maxd;
/* init the edge list */
for (int n = 0; n < NODES; n++) {
for (int p = 0; p < MAXPEERS; p++) {
edges[n][p] = -1;
}
}
/* suck the edges into memory from stdin */
read_edges();
/* fill out each row of the matrix one at a time */
maxd = 0;
for (int i = 0; i < NODES; i++) {
row_bfs(i, &maxd);
}
return 0;
}
void row_bfs(int32_t row, int *maxd) {
int d = 1; /* depth */
int n; /* working node */
int nn; /* new node */
int clptr; /* pointer into cl list */
int8_t dist_r[NODES]; /* the row of distances */
int32_t cl[NODES], nl[NODES];
dist_r[row] = 0; /* this node is adjacent to itself (distance 0) */
/* init the row and the current list */
for (int i = 0; i < NODES; i++) {
dist_r[i] = -1;
cl[i] = -1;
}
/* init the current with this row's direct peers */
for (int i = 0; i < MAXPEERS; i++) {
cl[i] = edges[row][i];
}
while (cl[0] != -1) { /* until there is nothing left in the current list */
/*fprintf(stderr, "Doing depth %d\n", d);*/
if (d > *maxd) {
*maxd = d;
fprintf(stderr, "Found new maximum depth: %d\n", d);
}
/* init the new list */
for (int i = 0; i < NODES; i++) {
nl[i] = -1;
}
/* all the current nodes are at distance d */
for (int i = 0; i < NODES; i++) {
n = cl[i];
if (n != -1) {
/* we're at depth d so this node is reachable at depth d */
dist_r[n] = d;
}
else {
break;
}
}
/* now we need to find the new nodes reachable at the next depth */
for (int i = 0; i < NODES; i++) {
n = cl[i];
if (n == -1) {
break;
}
/* follow the edges from this current node to the next nodes */
for (int j = 0; j < MAXPEERS; j++) {
nn = edges[n][j];
if (nn == -1) {
break;
}
/* this is a node reachable next depth */
if (dist_r[nn] == -1) {
nl[nn] = nn;
}
}
}
/* this depth is done, we need to copy the next list to the current list */
clptr = 0;
for (int i = 0; i < NODES; i++) {
nn = nl[i];
if (nn == -1) {
continue;
}
cl[clptr] = nn;
clptr++;
}
if (clptr < NODES) {
cl[clptr] = -1;
}
d++; /* we need to go deeper! */
} /* end while the current list isn't empty */
}
void read_edges() {
int scanret, lnum, ecount, byte;
int32_t e1, e2;
lnum = 0;
ecount = 0;
while (1) {
scanret = fscanf(stdin, "%d,%d\n", &e1, &e2);
lnum++;
if (scanret == EOF) {
lnum--;
break;
}
else if (scanret != 2) {
fprintf(stderr, "Got bogus edge on input line number %d\n", lnum);
/* need to advance input past this bogus line */
while (1) {
byte = fgetc(stdin);
if ((byte == '\n') || (byte == EOF)) {
break;
}
}
continue; /* move on to the next line */
}
else {
ecount += add_edge(e1, e2); /* count this edge */
add_edge(e2, e1); /* don't count this edge (undirected graph) */
}
} /* end while (1) */
fprintf(stderr, "Read %d lines and got %d distinct edges\n", lnum, ecount);
}
int add_edge(int32_t n, int32_t p) {
assert(n >= 0);
assert(p >= 0);
assert(n < NODES);
assert(p < NODES);
return add_peer(p, &(edges[n]), MAXPEERS);
}
int add_peer(int32_t p, int32_t (*plist)[], int len) {
for (int i = 0; i < len; i++) {
if ((*plist)[i] == -1) {
(*plist)[i] = p;
return 1;
}
else if ((*plist)[i] == p) {
return 0;
}
}
fprintf(stderr, "Maximum peer list exceeded %d!\n", len);
abort();
return -1; /* not reachable with above abort */
}