I find your data structure for your network a bit complicated. You have essentially two graphs (cw and cww) that share their vertices, but not their edges and exit and entry points.
The implementation below defines separate graphs and joins these in a network of graphs. You can create lists of shortest paths for each graph with breadth-first search as Juvian proposed. Then you can combine these lists for all graphs.
The code below ist just the path-seeking without GUI and fiddle:
// Return an object that contains a path for each
// possible exit point
function find_exits(g, id, func) {
var visited = {};
var list = {};
var v = g[id];
var q = [[id, [id]]];
visited[id] = true;
if (v.exit) list[id] = [id];
while (q.length) {
var x = q.shift();
var path = x[1];
id = x[0];
v = g[id];
for (var i = 0; i < v.edge.length; i++) {
var next = v.edge[i];
if (next in visited) continue;
visited[next] = true;
if (g[next].exit) {
list[next] = path.concat([next]);
}
q.push([next, path.concat([next])]);
}
path.pop();
}
return list;
}
// Combine two exit lists, choose the shorter path if there
// is an exit in both lists
function union(a, b) {
var u = {};
for (var x in a) u[x] = a[x];
for (var x in b) {
if (x in a && a[x].length < b[x].length) continue;
u[x] = b[x];
}
return u;
}
var cw = {
A: {
entry: true,
edge: ['B']
},
B: {
entry: true,
exit: true,
edge: ['C']
},
C: {
entry: true,
edge: ['D']
},
D: {
edge: ['E', 'F']
},
E: {
exit: true
},
F: {
entry: true,
exit: true,
edge: ['G']
},
G: {
exit: true,
edge: ['H']
},
H: {
edge: ['A']
}
};
var ccw = {
A: {
edge: ['H']
},
B: {
entry: true,
edge: ['A']
},
C: {
exit: true,
edge: ['B']
},
D: {
entry: true,
edge: ['C']
},
E: {
entry: true,
edge: ['D']
},
F: {
entry: true,
exit: true,
edge: ['D']
},
G: {
entry: true,
edge: ['F']
},
H: {
edge: ['G']
}
};
// Housekeeping object for a network of several sub-graphs
var network = {
graphs: [cw, ccw],
traverse: function(func) {
for (var i = 0; i < this.graphs.length; i++) {
func(this.graphs[i]);
}
}
}
// Ensure that every vertex has edge, exit, entry
network.traverse(function(g) {
for (var id in g) {
var v = g[id];
if (!("edge" in v)) v.edge = [];
if (!("entry" in v)) v.entry = false;
if (!("exit" in v)) v.exit = false;
}
});
// Actual path-seeking
var start = 'B';
var exits = {};
network.traverse(function(g) {
if (g[start].entry) {
exits = union(exits, find_exits(g, start));
}
});
console.log(exits);
This example doesn't show which of the graphs the actual path is for, but that could be added easily, I think.