2

enter image description here

How can I remove all cycles from a graph like this? All edge lengths are one, and all edges are either vertical or horizontal. The graph is connected.

I want to compute the smallest number of edges that have to be removed in order for the graph to contain no cycles.

It would be really helpful if you included sample code (preferably C++, C or Java).

UPDATE: Apparently I have to find the number of vertices and edges. The problem I have gives a set of instructions like (down, left, up, down, left, left, up, down). You start from (0, 0) in the coordinate plane and move one unit in the specified direction. This will create a graph. How would I get the number of vertices and edges from this set of instructions?

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Bob Billy
  • 285
  • 1
  • 6

2 Answers2

2

Since the graph is connected, if the point is, as you write, to

compute the smallest number of edges that need to be removed in order for the graph to contain no cycles

then you don't really need to write an algorithm. It is well known that the result of removing cycles is a tree, and all trees have the same number of edges (the number of vertices minus one).


If the point is to actually enumerate the remaining edges (or removed edges), then you can use DFS (depth first search). Specificially, in the output of DFS, you need to retain only what is marked there as "tree edges".

While there are C++ libraries for DFS, they might not enumerate the edges this way, and it might be easier to code this on your own. As you can see, the pseudocode is quite simple.

Ami Tavory
  • 74,578
  • 11
  • 141
  • 185
  • First of all, thank you so much for your answer. Unfortunately I am still stuck. The problem I have gives a set of instructions like (down, left, up, down, left, left, up, down). You start from (0, 0) in the coordinate plane and move one unit in the specified direction. This will create a graph. How would I get the number of vertices and edges from this set of instructions? – Bob Billy Jan 16 '16 at 06:21
  • @BobBilly You're welcome. I suggest that you start a new question on that (I'll be happy to answer if I see it): 1. It's really a different topic (graph representation from a grid), and 2) SO is not really built for a dialog within these comments. – Ami Tavory Jan 16 '16 at 07:05
  • Nvm I found out Yeah I would've started a new question if I needed more help – Bob Billy Jan 16 '16 at 07:09
0

To draw a graph based on directions (up, down, left, right), and keep a count of vertices, edges (and derived from that: elementary cycles), you could:

  • keep record of the current x, y coordinate -- a "turtle";
  • keep a set of visited vertices, so you only count unique instances;
  • do the same for edges, or more memory-efficiently: see if the latest move includes at least one point that was not visited before, and is not the reverse of the previous move: if so, count it as an edge.

Here is a JavaScript implementation that -- as a bonus -- also draws the graph:

function countEdgesAndVertices(directions, callback) {
    var turtle = [0, 0],
        vertices = {},
        revisit = false,
        edgeCount = 0,
        delta = {l: [-1, 0], r: [1, 0], u: [0, -1], d: [0, 1]},
        opposite = {l: 'r', r: 'l', u: 'd', d: 'u'},
        oppositeDir = '';
    vertices[turtle.join(',')] = true;
    directions.split('').forEach(function(dir) {
        if (!delta[dir]) return; // ignore invalid characters
        // Move turtle in given direction
        turtle[0] += delta[dir][0];
        turtle[1] += delta[dir][1];
        // Call caller's callback function with this vertex
        if (callback) callback(turtle);
        vertexId = turtle.join(',');
        // If this created a new edge, count it
        if (!vertices[vertexId] || !revisit && dir != oppositeDir) edgeCount++;
        // Remember whether we were here before
        revisit = vertices[vertexId];
        // Add vertice to set
        vertices[vertexId] = true;
        // Remember direction, so we wont count a move
        // in the opposite direction as a new edge
        oppositeDir = opposite[dir];
    });
    return {
        edges: edgeCount,
        vertices: Object.keys(vertices).length
    }
}

// IO
var input = document.querySelector('input');
var output = document.querySelector('span');
var canvas = document.querySelector('canvas');
var canvasContext;

// Drawing routines
function canvasDrawTo(vertex) {
    var scale = canvas.height/10;
    console.log('line to ', vertex[0],vertex[1]);
    canvasContext.lineTo(vertex[0]*scale,vertex[1]*scale);
    canvasContext.stroke();
}

function canvasClear(vertex) {
    canvas.width = canvas.width; // not nice, but this resets canvas
    canvasContext = canvas.getContext("2d");
    canvasContext.translate(canvas.width/2,canvas.height/2);
    canvasContext.beginPath();
    canvasContext.lineTo(0,0);
}

function update() {
    canvasClear();
    var result = countEdgesAndVertices(input.value, canvasDrawTo);
    output.textContent = 'Vertices: ' + result.vertices +
        '; Edges: ' + result.edges + 
        '; Non-divisable cycles: ' + (result.edges - result.vertices + 1);
};

// call update on any input change:
input.oninput = update;
// call update on load
update();
String of directions (u=up,d=down,l=left,r=right):<br>
<input type="text" size="40" value="uldrdddurulurdrdluurdur"><br>
Result: <span></span><br>
<canvas width="200" height="100"></canvas>

The results are updated real-time as you change the input.

trincot
  • 317,000
  • 35
  • 244
  • 286