--- /dev/null
+#include "graph/prim.h"
+#include "graph/search.h"
+#include <errno.h>
+#include <stdlib.h>
+
+/*
+ * todo priority queue, currently its broken
+ * */
+
+static int
+prim_ (struct graph *g, struct graph *pt, struct state *vs, unsigned int ri,
+ unsigned int (*w) (unsigned int, unsigned int))
+{
+ struct squeue sq;
+ struct vertex *r, *n;
+ struct state *rs, *ns;
+ struct edge *e;
+ unsigned int ni;
+ int err;
+
+ if (!(sq.q = calloc (g->nv, sizeof *sq.q)))
+ return -errno;
+
+ sq.f = sq.l = sq.q;
+ *sq.f = &g->v[ri];
+ vs[ri].c = RED;
+
+ while (sq.f <= sq.l)
+ {
+ r = *sq.f;
+ ri = vertex_id (g, r);
+ rs = &vs[ri];
+ e = r->adj;
+
+ while (e && (n = e->to))
+ {
+ ni = vertex_id (g, n);
+ ns = &vs[ni];
+
+ switch (ns->c)
+ {
+ case WHITE:
+ ns->c = RED;
+
+ if ((err = add_arc (pt, ri, ni)))
+ {
+ free (sq.q);
+ return err;
+ }
+
+ ns->w = w (ri, ni);
+ ns->from = r;
+
+ *(++sq.l) = n;
+ break;
+
+ case RED:
+ if (ns->w < w (ri, ni))
+ break;
+
+ del_arc (pt, vertex_id (g, ns->from), ni);
+
+ if ((err = add_arc (pt, ri, ni)))
+ {
+ free (sq.q);
+ return err;
+ }
+
+ ns->w = w (ri, ni);
+ ns->from = r;
+
+ break;
+ }
+
+ e = e->next;
+ }
+
+ rs->c = BLUE;
+ ++sq.f;
+ }
+
+ free (sq.q);
+ return 0;
+}
+
+struct graph *
+prim (struct graph *g, unsigned int (*w) (unsigned int, unsigned int))
+{
+ struct graph *pt;
+ struct state *vs;
+ unsigned int vi;
+
+ if (!(pt = new_graph (g->nv)))
+ goto err_new_graph;
+
+ if (!(vs = calloc (g->nv, sizeof *vs)))
+ goto err_calloc;
+
+ for (vi = 0; vi < g->nv; ++vi)
+ if (vs[vi].c == WHITE)
+ if (prim_ (g, pt, vs, vi, w))
+ goto err_prim_;
+
+ free (vs);
+ return pt;
+
+err_prim_:
+ free (vs);
+err_calloc:
+ free_graph (pt);
+err_new_graph:
+ return NULL;
+}