00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <ctype.h>
00012 #include <stdlib.h>
00013 #include <string.h>
00014 #include <stdio.h>
00015
00016 typedef struct __v {
00017 struct __v *next;
00018 int indegree,
00019 visited,
00020 on_the_path,
00021 has_a_cycle;
00022 struct __e *out;
00023 char key[1];
00024 } vertex;
00025
00026 typedef struct __e {
00027 struct __e *next;
00028 vertex *v;
00029 } edge;
00030
00031 _PROTOTYPE(int main, (int argc, char **argv));
00032 _PROTOTYPE(void *xmalloc, (size_t siz));
00033 _PROTOTYPE(edge *new_edge, (vertex *v));
00034 _PROTOTYPE(char *copyupto, (char *name, char *buf, int stop));
00035 _PROTOTYPE(int child_of, (vertex *parent, vertex *child));
00036 _PROTOTYPE(vertex *add_v, (char *s));
00037 _PROTOTYPE(void readin, (void));
00038 _PROTOTYPE(void pushname, (char *s));
00039 _PROTOTYPE(char *popname, (void));
00040 _PROTOTYPE(void topo, (void));
00041 _PROTOTYPE(void print_cycle, (vertex *parent, vertex *child));
00042 _PROTOTYPE(void dfs, (vertex *v));
00043 _PROTOTYPE(void check_cycles, (void));
00044
00045
00046
00047
00048 void *
00049 xmalloc(siz)
00050 size_t siz;
00051 {
00052 void *rval = (void *)malloc(siz);
00053 if(rval == NULL) {
00054 fputs("Out of memory.\n",stderr);
00055 exit(1);
00056 }
00057 return rval;
00058 }
00059
00060
00061
00062
00063 edge *
00064 new_edge(v)
00065 vertex *v;
00066 {
00067 edge *rval;
00068 rval = (edge *)xmalloc(sizeof(edge));
00069 rval->v = v; return rval;
00070 }
00071
00072
00073
00074
00075 char *
00076 copyupto(name,buf,stop)
00077 char *name,*buf,stop;
00078 {
00079 while(*buf != '\0' && *buf != stop)
00080 *name++ = *buf++;
00081 *name = '\0';
00082 while(*buf != '\0' && isspace(*buf))
00083 buf++;
00084 return buf;
00085 }
00086
00087
00088
00089
00090 int
00091 child_of(parent,child)
00092 vertex *parent,*child;
00093 {
00094 edge *e;
00095 for(e = parent->out; e != NULL && e->v != child; e = e->next)
00096 ;
00097 return e == NULL ? 0 : 1;
00098 }
00099
00100
00101
00102
00103
00104
00105 vertex *vset = NULL;
00106
00107 vertex *
00108 add_v(s)
00109 char *s;
00110 {
00111 vertex *v,*last;
00112
00113
00114
00115 for(last = v = vset; v != NULL && strcmp(v->key,s) != 0;
00116 last = v, v = v->next)
00117 ;
00118 if(v != NULL) {
00119
00120
00121
00122
00123 if(last != vset) {
00124 last->next = v->next;
00125 v->next = vset;
00126 vset = v;
00127 }
00128 return v;
00129 }
00130
00131 v = (vertex *)xmalloc(sizeof(vertex) + strlen(s));
00132
00133 v->out = NULL;
00134 strcpy(v->key,s);
00135 v->indegree =
00136 v->on_the_path =
00137 v->has_a_cycle =
00138 v->visited = 0;
00139 v->next = vset;
00140 vset = v;
00141 return v;
00142 }
00143
00144
00145
00146
00147 void
00148 readin()
00149 {
00150 static char buf[128];
00151 static char name[64];
00152 char *bp;
00153 vertex *child,*parent;
00154 edge *e;
00155 while(fgets(buf,sizeof(buf),stdin) != NULL) {
00156 bp = buf + strlen(buf);
00157 if (bp > buf && bp[-1] == '\n') *--bp = 0;
00158 bp = copyupto(name,buf,' ');
00159 child = add_v(name);
00160 parent = add_v(bp);
00161 if(child != parent && !child_of(parent,child)) {
00162 e = new_edge(child);
00163 e->next = parent->out;
00164 parent->out = e;
00165 child->indegree++;
00166 }
00167 }
00168 }
00169
00170
00171
00172
00173
00174
00175 struct name { struct name *next; char *s; }
00176 *namelist = NULL;
00177
00178 void
00179 pushname(s)
00180 char *s;
00181 {
00182 struct name *x = (struct name *)xmalloc(sizeof(struct name));
00183 x->s = s;
00184 x->next = namelist;
00185 namelist = x;
00186 }
00187
00188 char *
00189 popname() {
00190 char *rval;
00191 struct name *tmp;
00192 if(namelist == NULL)
00193 return NULL;
00194 tmp = namelist;
00195 rval = namelist->s;
00196 namelist = namelist->next;
00197 free(tmp);
00198 return rval;
00199 }
00200
00201
00202
00203
00204 void topo() {
00205 vertex *x = vset,*n;
00206 edge *e;
00207 vertex *outq = NULL,*tmp;
00208 #define insq(x) ((x->next = outq),(outq = x))
00209 #define deq() ((tmp = outq),(outq = outq->next),tmp)
00210
00211
00212
00213
00214
00215
00216 while (x != NULL) {
00217 n = x->next;
00218 if(x->indegree == 0) {
00219 insq(x);
00220 pushname(x->key);
00221 }
00222 x = n;
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 while(outq != NULL) {
00234 x = deq();
00235 e = x->out;
00236 while(e != NULL) {
00237 if(--(e->v->indegree) == 0) {
00238 insq(e->v);
00239 pushname(e->v->key);
00240 }
00241 e = e->next;
00242 }
00243 }
00244
00245
00246
00247
00248
00249 while(namelist != NULL)
00250 puts(popname());
00251 }
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 void
00264 print_cycle(parent,child)
00265 vertex *parent, *child;
00266 {
00267 char *s;
00268 vertex *x;
00269 edge *e;
00270 for(x = child; x != parent; ) {
00271 pushname(x->key);
00272 for(e = x->out; e != NULL; e = e->next) {
00273
00274
00275
00276
00277
00278
00279 if(e->v->on_the_path && !e->v->has_a_cycle) {
00280 x = e->v;
00281 break;
00282 }
00283 }
00284 }
00285
00286
00287
00288
00289 fprintf(stderr,"%s\n",x->key);
00290 while((s = popname()) != NULL)
00291 fprintf(stderr,"%s\n",s);
00292 }
00293
00294
00295
00296
00297
00298 void
00299 dfs(v)
00300 vertex *v;
00301 {
00302 edge *e;
00303
00304 if(v->visited)
00305 return;
00306 v->visited++;
00307 v->on_the_path++;
00308
00309
00310
00311
00312 for(e = v->out; e != NULL; e = e->next) {
00313 if(!e->v->visited)
00314 dfs(e->v);
00315 if(e->v->on_the_path) {
00316 fprintf(stderr,"cycle found between %s and %s\n",
00317 v->key,e->v->key);
00318 print_cycle(v,e->v);
00319 v->has_a_cycle++;
00320 }
00321 }
00322 v->on_the_path = 0;
00323 }
00324
00325
00326
00327
00328
00329 void
00330 check_cycles()
00331 {
00332 vertex *v;
00333 for(v = vset; v != NULL; v = v->next)
00334 dfs(v);
00335 }
00336
00337
00338
00339
00340 int main(argc,argv)
00341 int argc;
00342 char **argv;
00343 {
00344 if(argc > 1 && freopen(argv[1],"r",stdin) == NULL) {
00345 perror(argv[1]);
00346 exit(0);
00347 }
00348 if(argc > 2 && freopen(argv[2],"w",stdout) == NULL) {
00349 perror(argv[2]);
00350 exit(0);
00351 }
00352 readin();
00353 check_cycles();
00354 topo();
00355 return(0);
00356 }