/* * ACM ICPC - CERC 2011 * * Sample solution: regulate * Author: Zdenek Dvorak */ #include #include #define NV 20000 #define NE 100000 #define HTS 200011 #define NC 100 static struct edge { int f, t; struct edge *father, *l, *r; int owner, reversed; } edges[NE]; static struct { int mark; struct edge *e; } eh[HTS]; static int amark; static struct { int ncab; struct edge *cab[2]; } verts[NV+1][NC+1]; static int nv, ne, nc; static struct edge * eid (int f, int t, struct edge *set) { int h = (f * 65537 + 257 * t) % HTS; while (eh[h].mark == amark) { if (eh[h].e->f == f && eh[h].e->t == t) return eh[h].e; h++; if (h == HTS) h = 0; } if (set) { eh[h].e = set; eh[h].e->f = f; eh[h].e->t = t; eh[h].mark = amark; } return NULL; } static void clear_rev (struct edge *e) { struct edge *t; if (!e->reversed) return; t = e->l; e->l = e->r; e->r = t; if (e->l) e->l->reversed = !e->l->reversed; if (e->r) e->r->reversed = !e->r->reversed; e->reversed = 0; } static void rotate (struct edge *f, struct edge *e) { struct edge *el, *er; clear_rev (f); clear_rev (e); el = e->l; er = e->r; e->father = NULL; f->father = e; if (f->l == e) { e->r = f; f->l = er; if (er) er->father = f; } else { e->l = f; f->r = el; if (el) el->father = f; } } static void doublerot (struct edge *gf, struct edge *f, struct edge *e) { struct edge *el, *er, *fo; clear_rev (gf); clear_rev (f); clear_rev (e); el = e->l; er = e->r; e->father = gf->father; if (gf->father) { if (gf->father->l == gf) gf->father->l = e; else gf->father->r = e; } f->father = e; if (gf->l == f) { if (f->l == e) { fo = f->r; e->r = f; f->l = er; if (er) er->father = f; f->r = gf; gf->father = f; gf->l = fo; if (fo) fo->father = gf; } else { e->l = f; e->r = gf; gf->father = e; f->r = el; if (el) el->father = f; gf->l = er; if (er) er->father = gf; } } else { if (f->r == e) { fo = f->l; e->l = f; f->r = el; if (el) el->father = f; f->l = gf; gf->father = f; gf->r = fo; if (fo) fo->father = gf; } else { e->r = f; e->l = gf; gf->father = e; f->l = er; if (er) er->father = f; gf->r = el; if (el) el->father = gf; } } } static struct edge *apath[NV]; static int list_path (struct edge *e, int rev, int f) { rev ^= e->reversed; if (rev) { if (e->r) f = list_path (e->r, rev, f); apath[f++] = e; if (e->l) f = list_path (e->l, rev, f); } else { if (e->l) f = list_path (e->l, rev, f); apath[f++] = e; if (e->r) f = list_path (e->r, rev, f); } return f; } static void ver_path (struct edge *e) { int l = list_path (e, 0, 0); int tv, i; if (l == 1) return; if (apath[0]->f == apath[1]->f || apath[0]->f == apath[1]->t) tv = apath[0]->f; else tv = apath[0]->t; for (i = 1; i < l - 1; i++) { if (apath[i]->f == tv) tv = apath[i]->t; else tv = apath[i]->f; if (apath[i+1]->f != tv && apath[i+1]->t != tv) abort (); } } static void verify () { int i; for (i = 0; i < ne; i++) { struct edge *e = edges + i; if (e->l && (e->l->father != e || e->l->owner != e->owner)) abort (); if (e->r && (e->r->father != e || e->r->owner != e->owner)) abort (); if (!e->father) ver_path (e); } } static void splay (struct edge *e) { clear_rev (e); while (1) { if (!e->father) return; if (!e->father->father) { rotate (e->father, e); return; } doublerot (e->father->father, e->father, e); } } static void make_last (struct edge *e) { splay (e); if (e->l && e->r) abort (); if (e->r) e->reversed = 1; } static void make_first (struct edge *e) { splay (e); if (e->l && e->r) abort (); if (e->l) e->reversed = 1; } static void add_edge (int f, int t, int o, struct edge *e) { struct edge *l, *r; if (verts[f][o].ncab == 1) { l = verts[f][o].cab[0]; make_last (l); } else l = NULL; if (verts[t][o].ncab == 1) { r = verts[t][o].cab[0]; make_first (r); } else r = NULL; e->l = l; if (l) l->father = e; e->r = r; if (r) r->father = e; e->reversed = 0; e->owner = o; e->father = NULL; verts[f][o].cab[verts[f][o].ncab++] = e; verts[t][o].cab[verts[t][o].ncab++] = e; } static void rem_edge (int f, int t, struct edge *e) { int i; splay (e); if (e->l) e->l->father = NULL; if (e->r) e->r->father = NULL; for (i = 0; verts[f][e->owner].cab[i] != e; i++) continue; verts[f][e->owner].cab[i] = verts[f][e->owner].cab[--verts[f][e->owner].ncab]; for (i = 0; verts[t][e->owner].cab[i] != e; i++) continue; verts[t][e->owner].cab[i] = verts[t][e->owner].cab[--verts[t][e->owner].ncab]; e->l = NULL; e->r = NULL; e->father = NULL; e->owner = -1; } int main(void) { int nt, i, j, f, t, o, lne; struct edge *e; while (scanf ("%d%d%d%d", &nv, &lne, &nc, &nt) == 4) { if (!nv) break; amark++; for (i = 0; i < nv; i++) for (j = 0; j < nc; j++) verts[i+1][j+1].ncab = 0; for (ne = 0; ne < lne; ne++) { scanf ("%d%d%d", &f, &t, &o); eid (f, t, edges + ne); add_edge (f, t, o, edges + ne); } for (i = 0; i < nt; i++) { scanf ("%d%d%d", &f, &t, &o); e = eid (f, t, NULL); if (!e) { printf ("No such cable.\n"); continue; } if (e->owner == o) { printf ("Already owned.\n"); continue; } if (verts[f][o].ncab == 2 || verts[t][o].ncab == 2) { printf ("Forbidden: monopoly.\n"); continue; } if (verts[f][o].ncab > 0 && verts[t][o].ncab > 0) { splay (verts[f][o].cab[0]); splay (verts[t][o].cab[0]); if (verts[f][o].cab[0]->father) { printf ("Forbidden: redundant.\n"); continue; } } /* verify ();*/ rem_edge (f, t, e); /* verify ();*/ add_edge (f, t, o, e); /* verify ();*/ printf ("Sold.\n"); } printf("\n"); } return 0; }