DFS | BFS : Check if path exists between node A and node B - c#

In a bidirectional graph check if a path exists between node A and node B.
My code does not work for certain input (samples provided below). Is this implementation correct or I missed something?
bool[] visited = null;
public bool ValidPath(int n, int[][] edges, int start, int end) {
IList<int>[] adjacencyList = new List<int>[n];
visited = new bool[n];
// create adjacency list
for(int i = 0; i < edges.Length; i++){
int a = edges[i][0];
int b = edges[i][1];
if(adjacencyList[a] == null)
adjacencyList[a] = new List<int>();
adjacencyList[a].Add(b);
if(adjacencyList[b] == null)
adjacencyList[b] = new List<int>();
adjacencyList[b].Add(a);
}
return DFS(adjacencyList, start, end);
}
private bool DFS(IList<int>[] adjacencyList, int start, int end){
if(start == end) return true;
if(!visited[start]){
visited[start] = true;
foreach(var v in adjacencyList[start]){
if(v == end) return true;
if(!visited[v])
DFS(adjacencyList, v, end);
}
}
return false;
}
This works for below examples:
Input: n = 3, edges = [[0,1],[1,2],[2,0]], start = 0, end = 2
Output: true
Input: n = 6, edges = [[0,1],[0,2],[3,5],[5,4],[4,3]], start = 0, end = 5
Output: false
Does not work for below (expected return value is true but I get false):
Input: 10, edges = [[4,3],[1,4],[4,8],[1,7],[6,4],[4,2],[7,4],[4,0],[0,9],[5,4]], start = 5, end = 9

The approach is correct, with the only issue being that inside the recursive DFS, you need to keep track of the result of all the subsequent DFS calls. If any of the recursive calls return true, then the solution should return true (instead of directly returning false). Here is the slightly modified version of the DFS function that works :
private bool DFS(IList<int>[] adjacencyList, int start, int end){
if(start == end) return true;
bool status = false;
if(!visited[start]){
visited[start] = true;
foreach(var v in adjacencyList[start]){
if(v == end) {
return true;
}
if(!visited[v]) {
status = status || DFS(adjacencyList, v, end);
}
}
}
return status;
}
Update :
Thanks to the suggestion in the comments. If DFS for any of the adjacent vertices returns true, then the method can directly return true (instead of making DFS call for other adjacent vertices and keeping that status). That gives us another variation of DFS :
private bool DFS(IList<int>[] adjacencyList, int start, int end){
if (start == end) return true;
bool status = false;
if(!visited[start]){
visited[start] = true;
foreach(var v in adjacencyList[start]){
if(v == end) {
return true;
}
if(!visited[v] && DFS(adjacencyList, v, end)) {
return true;
}
}
}
return status;
}

Check this, it will pass all the testcases. It is based on BFS.
//int[][] edges = new int[][]
//{
// new int[] { 0, 1 },
// new int[] { 1, 2 },
// new int[] { 2, 0 }
//};
public static bool ValidPath(int[][] edges, int source, int destination)
{
if (source == destination) return true;
var graph = new Dictionary<int, List<int>>();
for (int i = 0; i < edges.Length; i++)
{
var pair = edges[i];
if (!graph.ContainsKey(pair[0])) graph.Add(pair[0], new List<int>());
if (!graph.ContainsKey(pair[1])) graph.Add(pair[1], new List<int>());
graph[pair[0]].Add(pair[1]);
graph[pair[1]].Add(pair[0]);
}
var visited = new HashSet<int>();
visited.Add(source);
var queue = new Queue<int>();
queue.Enqueue(source);
while (queue.Count > 0)
{
var vertex = queue.Dequeue();
if (vertex == destination) return true;
foreach (var next in graph[vertex])
{
if (visited.Contains(next)) continue;
visited.Add(next);
queue.Enqueue(next);
}
}
return false;
}

Related

Skip foreach X positions

I want skip my in foreach. For example:
foreach(Times t in timeList)
{
if(t.Time == 20)
{
timeList.Skip(3);
}
}
I want "jump" 3 positions in my list.. If, in my if block t.Id = 10 after skip I want get t.Id = 13
How about this? If you use a for loop then you can just step the index forward as needed:
for (var x = 0; x < timeList.Length; x++)
{
if (timeList[x].Time == 20)
{
// option 1
x += 2; // 'x++' in the for loop will +1,
// we are adding +2 more to make it 3?
// option 2
// x += 3; // just add 3!
}
}
You can't modify an enumerable in-flight, as it were, like you could the index of a for loop; you must account for it up front. Fortunately there are several way to do this.
Here's one:
foreach(Times t in timeList.Where(t => t.Time < 20 || t.Time > 22))
{
}
There's also the .Skip() option, but to use it you must break the list into two separate enumerables and then rejoin them:
var times1 = timeList.TakeWhile(t => t.Time != 20);
var times2 = timeList.SkipeWhile(t => t.Time != 20).Skip(3);
foreach(var t in times1.Concat(times2))
{
}
But that's not exactly efficient, as it requires iterating over the first part of the sequence twice (and won't work at all for Read Once -style sequences). To fix this, you can make a custom enumerator:
public static IEnumerable<T> SkipAt<T>(this IEnumerable<T> items, Predicate<T> SkipTrigger, int SkipCount)
{
bool triggered = false;
int SkipsRemaining = 0;
var e = items.GetEnumerator();
while (e.MoveNext())
{
if (!triggered && SkipTrigger(e.Current))
{
triggered = true;
SkipsRemaining = SkipCount;
}
if (triggered)
{
SkipsRemaining--;
if (SkipsRemaining == 0) triggered = false;
}
else
{
yield return e.Current;
}
}
}
Then you could use it like this:
foreach(Times t in timeList.SkipAt(t => t.Times == 20, 3))
{
}
But again: you still need to decide about this up front, rather than inside the loop body.
For fun, I felt like adding an overload that uses another predicate to tell the enumerator when to resume:
public static IEnumerable<T> SkipAt<T>(this IEnumerable<T> items, Predicate<T> SkipTrigger, Predicate<T> ResumeTrigger)
{
bool triggered = false;
var e = items.GetEnumerator();
while (e.MoveNext())
{
if (!triggered && SkipTrigger(e.Current))
{
triggered = true;
}
if (triggered)
{
if (ResumeTrigger(e.Current)) triggered = false;
}
else
{
yield return e.Current;
}
}
}
You can use continue with some simple variables.
int skipCount = 0;
bool skip = false;
foreach (var x in myList)
{
if (skipCount == 3)
{
skip = false;
skipCount = 0;
}
if (x.time == 20)
{
skip = true;
skipCount = 0;
}
if (skip)
{
skipCount++;
continue;
}
// here you do whatever you don't want to skip
}
Or if you can use a for-loop, increase the index like this:
for (int i = 0; i < times.Count)
{
if (times[i].time == 20)
{
i += 2; // 2 + 1 loop increment
continue;
}
// here you do whatever you don't want to skip
}

Prevent ' Process is terminated due to StackOverflowException' in C#

I have a program which builds a very large tree from input data and traverses it, both by recursion. I have tested the program on smaller inputs (and thus smaller trees) and it functions as intended. However when the input data is much larger i run into 'Process is terminated due to StackOverflowException'. I assume this is due to the stack running out of space. Is there any way to prevent this or do I have to switch to building the tree via iteration instead? Or perhaps I am missing a case of infinite recursion somewhere?
Here is the code:
class Program
{
static int[] tileColors;
static Color[] colors;
static int totalTiles;
static void Main(string[] args)
{
Stopwatch s = new Stopwatch();
s.Start();
string[] data = File.ReadAllLines("colors.txt");
totalTiles = int.Parse(data[0].Split(' ')[0]);
int totalColors = int.Parse(data[0].Split(' ')[1]);
string[] colorsRaw = data[1].Split(' ');
tileColors = new int[totalTiles];
for (int i = 0; i < totalTiles; i++)
{
tileColors[i] = int.Parse(colorsRaw[i]) - 1;
}
colors = new Color[totalColors];
for (int i = 3; i < data.Length; i++)
{
string[] raw = data[i].Split(' ');
int[] pair = new int[] { int.Parse(raw[0]) - 1, int.Parse(raw[1]) - 1 };
if (colors[pair[0]] == null)
colors[pair[0]] = new Color(pair[1]);
else
colors[pair[0]].pairs.Add(pair[1]);
if (colors[pair[1]] == null)
colors[pair[1]] = new Color(pair[0]);
else
colors[pair[1]].pairs.Add(pair[0]);
}
Tree t = new Tree();
t.root = new Node(0);
PopulateTree(t.root);
long ans = t.CountMatchingLeaves(t.root, totalTiles - 1) % 1000000007;
Console.WriteLine(ans);
s.Stop();
Console.WriteLine(s.ElapsedMilliseconds);
}
static void PopulateTree(Node root)
{
for (int i = root.tile + 1; i < totalTiles; i++)
{
if (colors[tileColors[i]] == null) continue;
if (colors[tileColors[i]].Compatible(tileColors[root.tile]))
{
var node = new Node(i);
root.children.Add(node);
PopulateTree(node);
}
}
}
}
class Color
{
public List<int> pairs = new List<int>();
public Color(int pair)
{
pairs.Add(pair);
}
public bool Compatible(int c)
{
return pairs.Contains(c);
}
}
class Node
{
public List<Node> children = new List<Node>();
public int tile;
public Node(int tile)
{
this.tile = tile;
}
}
class Tree
{
public Node root;
public List<Node> GetMatchingLeaves(Node root, int match)
{
if (root.children.Count == 0)
{
if (root.tile == match)
{
return new List<Node>() { root };
}
return new List<Node>();
}
List<Node> list = new List<Node>();
foreach(var c in root.children)
{
list.AddRange(GetMatchingLeaves(c, match));
}
return list;
}
public long CountMatchingLeaves(Node root, int match)
{
if (root.children.Count == 0)
{
if (root.tile == match)
{
return 1;
}
return 0;
}
long count = 0;
foreach (var c in root.children)
{
count += CountMatchingLeaves(c, match);
}
return count;
}
}
You can always rewrite recursion as iteration, usually by using a stack class rather than rely on your thread's stack. For your code it would look like this:
static void PopulateTree(Node start)
{
var nodes = new Stack<Node>();
nodes.Push(start);
while(nodes.Count != 0)
{
var root = nodes.Pop();
for (int i = root.tile + 1; i < totalTiles; i++)
{
if (colors[tileColors[i]] == null) continue;
if (colors[tileColors[i]].Compatible(tileColors[root.tile]))
{
var node = new Node(i);
root.children.Add(node);
nodes.Push(node);
}
}
}
}
The while loop checking for more items is the equivalent of your terminating condition in recursion.

In C#, how would I add diagonals to my A Star path finding class?

I have a simple path finding class using A*, however it only covers the four cardinal directions in a tile map. It obeys walls and avoids them, but in open spaces it creates a zig-zag pattern to get to it's destination.
I'd like to simplify that pattern to include diagonals - in open areas of the map, but so far if I use diagonals, it seems to ignore the walls entirely.
How can I solve this and correctly add the diagonals?
using UnityEngine;
using System.Collections.Generic;
public class AStar {
private List<Node> openList;
private List<Node> closeList;
private List<Node> neighbors;
private List<Node> finalPath;
private Node start;
private Node end;
public AStar()
{
openList = new List<Node>();
closeList = new List<Node>();
neighbors = new List<Node>();
finalPath = new List<Node>();
}
public void FindPath(MazeCell startCell, MazeCell goalCell)
{
start = new Node(0, 0, 0, null, startCell);
end = new Node(0, 0, 0, null, goalCell);
openList.Add(start);
bool keepSearching = true;
bool pathExists = true;
while(keepSearching && pathExists)
{
Node currentNode = ExtractBestNodeFromOpenList();
if (currentNode == null)
{
pathExists = false;
break;
}
closeList.Add(currentNode);
if (NodeIsGoal(currentNode))
{
keepSearching = false;
} else
{
FindValidFourNeighbors(currentNode);
}
foreach(Node neighbor in neighbors)
{
if (FindInList(neighbor, closeList) != null)
continue;
Node inOpenList = FindInList(neighbor, openList);
if (inOpenList == null)
{
openList.Add(neighbor);
} else
{
if (neighbor.G < inOpenList.G)
{
inOpenList.G = neighbor.G;
inOpenList.F = inOpenList.G + inOpenList.H;
inOpenList.parent = currentNode;
}
}
}
}
if (pathExists)
{
Node n = FindInList(end, closeList);
while (n != null)
{
finalPath.Add(n);
n = n.parent;
}
}
}
public bool ContainsCoordinates(IntVector2 coordinate)
{
return coordinate.x >= 0 && coordinate.x < GameConfig.mazeSize && coordinate.z >= 0 && coordinate.z < GameConfig.mazeSize;
}
private void FindValidFourNeighbors(Node node)
{
neighbors.Clear();
// Check South of this Cell //
int south = node.cell.mazeCellCoordinates.z - 1;
IntVector2 SouthNeighbor = new IntVector2(node.cell.mazeCellCoordinates.x , south);
int north = node.cell.mazeCellCoordinates.z + 1;
IntVector2 NorthNeighbor = new IntVector2(node.cell.mazeCellCoordinates.x, north);
int east = node.cell.mazeCellCoordinates.x + 1;
IntVector2 EastNeighbor = new IntVector2(east, node.cell.mazeCellCoordinates.z);
int west = node.cell.mazeCellCoordinates.x - 1;
IntVector2 WestNeighbor = new IntVector2(west, node.cell.mazeCellCoordinates.z);
IntVector2 SouthEastNeighbor = new IntVector2(south, east);
IntVector2 SouthWestNeighbor = new IntVector2(south, west);
IntVector2 NorthEastNeighbor = new IntVector2(north, east);
IntVector2 NorthWestNeighbor = new IntVector2(north, west);
if (ContainsCoordinates(SouthNeighbor))
{
if (Maze.Instance.cellStorage[SouthNeighbor.x, SouthNeighbor.z].IsWalkable)
{
MazeCell c = Maze.Instance.cellStorage[SouthNeighbor.x, SouthNeighbor.z];
if (!(c.cellEdges[(int)MazeDirection.North] is MazeCellWall))
{
Node vn = PrepareNewNode(node, 0, -1);
neighbors.Add(vn);
}
}
}
if (ContainsCoordinates(NorthNeighbor))
{
if (Maze.Instance.cellStorage[NorthNeighbor.x, NorthNeighbor.z].IsWalkable)
{
MazeCell c = Maze.Instance.cellStorage[NorthNeighbor.x, NorthNeighbor.z];
if (!(c.cellEdges[(int)MazeDirection.South] is MazeCellWall))
{
Node vn = PrepareNewNode(node, 0, 1);
neighbors.Add(vn);
}
}
}
if (ContainsCoordinates(WestNeighbor))
{
if (Maze.Instance.cellStorage[WestNeighbor.x, WestNeighbor.z].IsWalkable)
{
MazeCell c = Maze.Instance.cellStorage[WestNeighbor.x, WestNeighbor.z];
if (!(c.cellEdges[(int)MazeDirection.East] is MazeCellWall))
{
Node vn = PrepareNewNode(node, -1, 0);
neighbors.Add(vn);
}
}
}
if (ContainsCoordinates(EastNeighbor))
{
if (Maze.Instance.cellStorage[EastNeighbor.x, EastNeighbor.z].IsWalkable)
{
MazeCell c = Maze.Instance.cellStorage[EastNeighbor.x, EastNeighbor.z];
if (!(c.cellEdges[(int)MazeDirection.West] is MazeCellWall))
{
Node vn = PrepareNewNode(node, 1, 0);
neighbors.Add(vn);
}
}
}
}
private float Heuristic(Node n)
{
return Mathf.Sqrt((n.cell.mazeCellCoordinates.x - end.cell.mazeCellCoordinates.x) * (n.cell.mazeCellCoordinates.x - end.cell.mazeCellCoordinates.x) + (n.cell.mazeCellCoordinates.z - end.cell.mazeCellCoordinates.z) * (n.cell.mazeCellCoordinates.z - end.cell.mazeCellCoordinates.z));
}
private float MovementCost(Node a, Node b)
{
return Maze.Instance.cellStorage[b.cell.mazeCellCoordinates.x, b.cell.mazeCellCoordinates.z].movementCost();
}
private Node PrepareNewNode(Node n, int x, int z)
{
IntVector2 iv = new IntVector2(n.cell.mazeCellCoordinates.x + x, n.cell.mazeCellCoordinates.z + z);
Node node = new Node(0, 0, 0, n, Maze.Instance.cellStorage[iv.x, iv.z]);
node.G = n.G + MovementCost(n, node);
node.H = Heuristic(node);
node.F = node.G + node.H;
node.parent = n;
return node;
}
public List<MazeCell> CellsFromPath()
{
List<MazeCell> path = new List<MazeCell>();
foreach (Node n in finalPath)
{
path.Add(n.cell);
}
if (path.Count != 0)
{
path.Reverse();
path.RemoveAt(0);
}
return path;
}
public List<int> PointsFromPath()
{
List<int> points = new List<int>();
foreach (Node n in finalPath)
{
points.Add(n.cell.mazeCellCoordinates.x);
points.Add(n.cell.mazeCellCoordinates.z);
}
return points;
}
bool NodeIsGoal(Node node)
{
return ((node.cell.mazeCellCoordinates.x == end.cell.mazeCellCoordinates.x) && (node.cell.mazeCellCoordinates.z == end.cell.mazeCellCoordinates.z));
}
Node FindInList(Node n, List<Node> xl)
{
foreach (Node nn in xl)
{
if ((nn.cell.mazeCellCoordinates.x == n.cell.mazeCellCoordinates.x) && (nn.cell.mazeCellCoordinates.z == n.cell.mazeCellCoordinates.z))
return nn;
}
return null;
}
private Node ExtractBestNodeFromOpenList()
{
float minF = float.MaxValue;
Node bestNode = null;
foreach(Node n in openList)
{
if (n.F < minF)
{
minF = n.F;
bestNode = n;
}
}
if (bestNode != null)
openList.Remove(bestNode);
return bestNode;
}
}
I have implemented an A* before with diagonals and you just need to include them in the list of viable neighbors.
Technically you should do the costing/exclusion in your heuristic function rather, but just looking at your code surely you could just add 4 more checks in private void FindValidFourNeighbors(Node node):
if (ContainsCoordinates(SouthEastNeighbor))
{
if (Maze.Instance.cellStorage[SouthEastNeighbor.x, SouthEastNeighbor.z].IsWalkable)
{
MazeCell c = Maze.Instance.cellStorage[SouthEastNeighbor.x, SouthEastNeighbor.z];
if (!(c.cellEdges[(int)MazeDirection.South] is MazeCellWall) && !(c.cellEdges[(int)MazeDirection.East] is MazeCellWall))
{
Node vn = PrepareNewNode(node, 0, -1);
neighbors.Add(vn);
}
}
}
(Not too clear what the 'cellEdges' check is doing exactly but I assume you would need to check both sides for the diagonal and this is maybe where you are failing.)

Calculate Preorder Tree Traversal From DataTable structure

I have a DataTable that has the following structure:
Root | Level 1 | Level 2 | Level 3 | Tree L | Tree R
Food 1 18
Fruit 2 11
Red 3 6
Cherry 4 5
Yellow 7 10
Banana 8 9
Meat 12 17
Beef 13 14
Pork 15 16
Using C#, I need to traverse this structure and calculate the correct Tree L and Tree R values for each node. This is just an example, the real structure has several hundred nodes that go out to at least Level 7, but possibly more.
Can anyone suggest how I might approach the code for calculating the left and right values?
So, you want to keep track of the visit order of the tree, but you have the order split into L and R. Those correspond to the "entrance" and "exit" of the Visit function for the Node structure. Assuming a Node class with a Node.Visit() method, you could:
private static List<Tuple<char,Node>> VisitOrder = new List<Tuple<char,Node>>();
public void Visit()
{
VisitOrder.Add(Tuple.Create('L', this));
// whatever visit logic you use here
VisitOrder.Add(Tuple.Create('R', this));
}
When you finish, all you have to do is do is look at the VisitOrder values. They're stored in the List in increasing order, where the index corresponds to it's position in the visit sequence. Each item in the List, then, is a Tuple describing which value it corresponds to and which Node it visited.
Edit:
To get the final output format, you could then do something like:
var LTree = VisitOrder
.Where(t => t.First == 'L')
.Select((t, i) => String.Format("{0}) {1}", i + 1, t.Second.Name));
var RTree = VisitOrder
.Where(t => t.First == 'R')
.Select((t, i) => String.Format("{0}) {1}", i + 1, t.Second.Name));
Here is how I figured it out:
private class FolderRow
{
public int Indent
{
get { return this.Row.GetValue("Indent", 0); }
set { this.Row["Indent"] = value; }
}
public int Left
{
get { return this.Row.GetValue("Tree L", 0); }
set { this.Row["Tree L"] = value; }
}
public int Right
{
get { return this.Row.GetValue("Tree R", 0); }
set { this.Row["Tree R"] = value; }
}
public Guid Id
{
get { return this.Row.GetValue("FolderID", Guid.Empty); }
}
public DataRow Row { get; private set; }
public int RowNum { get; set; }
public bool RowComplete { get { return this.Left > 0 && this.Right > 0; } }
public FolderRow(DataRow row, int rowNum)
{
this.Row = row;
this.RowNum = rowNum;
}
}
[TestMethod]
public void ImportFolderStructure()
{
var inputTable = FileUtil.GetDataSetFromExcelFile(new FileInfo(#"c:\SampleTree.xlsx")).Tables[0];
var currentLevel = 0;
var nodeCount = 1;
var currentRow = 0;
inputTable.Columns.Add("Indent", typeof (int));
inputTable.Columns.Add("Path", typeof (string));
var rightStack = new List<FolderRow>();
foreach (DataRow row in inputTable.Rows)
row["Indent"] = GetLevelPopulated(row);
foreach (DataRow row in inputTable.Rows)
{
if (row.GetValue("Indent", 0) == 0)
row["Tree L"] = 1;
}
while (true)
{
var row = GetRow(inputTable, currentRow);
if (row.Indent == 0)
{
currentRow++;
rightStack.Add(row);
continue;
}
// if the indent of this row is greater than the previous row ...
if (row.Indent > currentLevel)
{
currentLevel++;
nodeCount++;
row.Left = nodeCount;
// ... check the next row to see if it is further indented
currentRow = HandleNextRow(row, currentRow, rightStack, inputTable, ref currentLevel, ref nodeCount);
} else if (row.Indent == currentLevel)
{
nodeCount++;
row.Left = nodeCount;
currentRow = HandleNextRow(row, currentRow, rightStack, inputTable, ref currentLevel, ref nodeCount);
} else if (row.Indent < currentLevel)
{
currentLevel--;
nodeCount++;
row.Left = nodeCount;
currentRow = HandleNextRow(row, currentRow, rightStack, inputTable, ref currentLevel, ref nodeCount);
}
if (inputTable.Rows.Cast<DataRow>().Select(r => new FolderRow(r, -1)).All(r => r.RowComplete))
break;
}
}
private int HandleNextRow(FolderRow row, int currentRow, List<FolderRow> rightStack, DataTable inputTable, ref int currentLevel,
ref int nodeCount)
{
var nextRow = GetRow(inputTable, currentRow + 1);
if (nextRow != null)
{
if (nextRow.Indent > row.Indent)
{
// ok the current row has a child so we will need to set the tree right of that, add to stack
rightStack.Add(row);
}
else if (nextRow.Indent == row.Indent)
{
nodeCount++;
row.Right = nodeCount;
}
else if (nextRow.Indent < row.Indent)
{
nodeCount++;
row.Right = nodeCount;
nodeCount++;
// here we need to get the most recently added row to rightStack, set the Right to the current nodeCount
var stackLast = rightStack.LastOrDefault();
if (stackLast != null)
{
stackLast.Right = nodeCount;
rightStack.Remove(stackLast);
}
currentLevel--;
}
currentRow++;
if (rightStack.Count > 1)
{
// before we move on to the next row, we need to check if there is more than one row still in right stack and
// the new current row's ident is less than the current branch (not current leaf)
var newCurrentRow = GetRow(inputTable, currentRow);
var stackLast = rightStack.LastOrDefault();
if (newCurrentRow.Indent == stackLast.Indent)
{
nodeCount++;
stackLast.Right = nodeCount;
rightStack.Remove(stackLast);
}
}
}
else
{
// reached the bottom
nodeCount++;
row.Right = nodeCount;
// loop through the remaining items in rightStack and set their right values
var stackLast = rightStack.LastOrDefault();
while (stackLast != null)
{
nodeCount++;
stackLast.Right = nodeCount;
rightStack.Remove(stackLast);
stackLast = rightStack.LastOrDefault();
}
}
return currentRow;
}
private FolderRow GetRow(DataTable inputTable, int rowCount)
{
if (rowCount >= inputTable.Rows.Count)
return null;
return rowCount < 0 ? null : new FolderRow(inputTable.Rows[rowCount],rowCount);
}
private int GetLevelPopulated(DataRow row)
{
var level = 0;
while (level < 14)
{
if (level == 0 && row["Root"] != DBNull.Value)
return level;
level++;
if (row["Level " + level] != DBNull.Value)
return level;
}
return -1;
}

How can I compute the minimum bipartite vertex cover?

How can I compute the minimum bipartite vertex cover in C#? Is there a code snippet to do so?
EDIT: while the problem is NP-complete for general graphs, it is solvable in polynomial time for bipartite graphs. I know that it's somehow related to maximum matching in bipartite graphs (by Konig's theorem) but I can't understand the theorem correctly to be able to convert the result of maximum bipartite matching to vertex cover.
I could figure it out:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
class VertexCover
{
static void Main(string[] args)
{
var v = new VertexCover();
v.ParseInput();
v.FindVertexCover();
v.PrintResults();
}
private void PrintResults()
{
Console.WriteLine(String.Join(" ", VertexCoverResult.Select(x => x.ToString()).ToArray()));
}
private void FindVertexCover()
{
FindBipartiteMatching();
var TreeSet = new HashSet<int>();
foreach (var v in LeftVertices)
if (Matching[v] < 0)
DepthFirstSearch(TreeSet, v, false);
VertexCoverResult = new HashSet<int>(LeftVertices.Except(TreeSet).Union(RightVertices.Intersect(TreeSet)));
}
private void DepthFirstSearch(HashSet<int> TreeSet, int v, bool left)
{
if (TreeSet.Contains(v))
return;
TreeSet.Add(v);
if (left) {
foreach (var u in Edges[v])
if (u != Matching[v])
DepthFirstSearch(TreeSet, u, true);
} else if (Matching[v] >= 0)
DepthFirstSearch(TreeSet, Matching[v], false);
}
private void FindBipartiteMatching()
{
Bicolorate();
Matching = Enumerable.Repeat(-1, VertexCount).ToArray();
var cnt = 0;
foreach (var i in LeftVertices) {
var seen = new bool[VertexCount];
if (BipartiteMatchingInternal(seen, i)) cnt++;
}
}
private bool BipartiteMatchingInternal(bool[] seen, int u)
{
foreach (var v in Edges[u]) {
if (seen[v]) continue;
seen[v] = true;
if (Matching[v] < 0 || BipartiteMatchingInternal(seen, Matching[v])) {
Matching[u] = v;
Matching[v] = u;
return true;
}
}
return false;
}
private void Bicolorate()
{
LeftVertices = new HashSet<int>();
RightVertices = new HashSet<int>();
var colors = new int[VertexCount];
for (int i = 0; i < VertexCount; ++i)
if (colors[i] == 0 && !BicolorateInternal(colors, i, 1))
throw new InvalidOperationException("Graph is NOT bipartite.");
}
private bool BicolorateInternal(int[] colors, int i, int color)
{
if (colors[i] == 0) {
if (color == 1) LeftVertices.Add(i);
else RightVertices.Add(i);
colors[i] = color;
} else if (colors[i] != color)
return false;
else
return true;
foreach (var j in Edges[i])
if (!BicolorateInternal(colors, j, 3 - color))
return false;
return true;
}
private int VertexCount;
private HashSet<int>[] Edges;
private HashSet<int> LeftVertices;
private HashSet<int> RightVertices;
private HashSet<int> VertexCoverResult;
private int[] Matching;
private void ReadIntegerPair(out int x, out int y)
{
var input = Console.ReadLine();
var splitted = input.Split(new char[] { ' ' }, 2);
x = int.Parse(splitted[0]);
y = int.Parse(splitted[1]);
}
private void ParseInput()
{
int EdgeCount;
ReadIntegerPair(out VertexCount, out EdgeCount);
Edges = new HashSet<int>[VertexCount];
for (int i = 0; i < Edges.Length; ++i)
Edges[i] = new HashSet<int>();
for (int i = 0; i < EdgeCount; i++) {
int x, y;
ReadIntegerPair(out x, out y);
Edges[x].Add(y);
Edges[y].Add(x);
}
}
}
As you can see, this code solves the problem in polynomial time.
Its probably best to just go ahead and pick a node at random. For each node, either it goes in the vertex cover, or all of its neighbors do (since you need to include that edge). The end-result of the whole thing will be a set of vertex covers, and you pick the smallest one. I"m not going to sit here and code it out, though, since if I remember correctly, its NP complete.
private void DepthFirstSearch(HashSet TreeSet, int v, bool left)
{
if (TreeSet.Contains(v))
return;
TreeSet.Add(v);
if (left) {
foreach (var u in Edges[v])
if (u != Matching[v])
DepthFirstSearch(TreeSet, u, true);
} else if (Matching[v] >= 0)
DepthFirstSearch(TreeSet, Matching[v], false);
}
when the if(left) will execute i am figuring that it's value is always will be false.

Categories

Resources