155 lines
4.0 KiB
C#
155 lines
4.0 KiB
C#
using Assets.Common;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Assets.Map
|
|
{
|
|
[Serializable]
|
|
public class Graph<T>
|
|
{
|
|
public List<T> Vertices { get; internal set; } = new List<T>();
|
|
private Dictionary<int, List<int>> _edges = new Dictionary<int, List<int>>();
|
|
|
|
public IEnumerable<(int, int)> Edges
|
|
{
|
|
get
|
|
{
|
|
return _edges.SelectMany(pair => pair.Value.Where(value => value > pair.Key).Select(value => (pair.Key, value)));
|
|
}
|
|
|
|
set
|
|
{
|
|
_edges = new Dictionary<int, List<int>>();
|
|
|
|
foreach (var (a, b) in value)
|
|
AddEdge(a, b);
|
|
}
|
|
}
|
|
|
|
public void AddEdge(int a, int b)
|
|
{
|
|
if (!_edges.ContainsKey(a))
|
|
_edges[a] = new List<int>();
|
|
|
|
if (!_edges.ContainsKey(b))
|
|
_edges[b] = new List<int>();
|
|
|
|
_edges[a].Add(b);
|
|
_edges[b].Add(a);
|
|
}
|
|
|
|
public void DeleteEdge(int a, int b)
|
|
{
|
|
if (!_edges.ContainsKey(a))
|
|
return;
|
|
|
|
if (!_edges.ContainsKey(b))
|
|
return;
|
|
|
|
_edges[a].Remove(b);
|
|
_edges[b].Remove(a);
|
|
}
|
|
|
|
public static bool HasCycle(Graph<T> graph)
|
|
{
|
|
int Find(int[] parent, int i)
|
|
{
|
|
if (parent[i] == -1)
|
|
return i;
|
|
|
|
return Find(parent, parent[i]);
|
|
}
|
|
|
|
void Union(int[] parent, int x, int y)
|
|
{
|
|
int xset = Find(parent, x);
|
|
int yset = Find(parent, y);
|
|
parent[xset] = yset;
|
|
}
|
|
|
|
int[] trueParent = new int[graph.Vertices.Count()];
|
|
|
|
for (int i = 0; i < graph.Vertices.Count(); ++i)
|
|
trueParent[i] = -1;
|
|
|
|
for (int i = 0; i < graph.Edges.Count(); ++i)
|
|
{
|
|
int x = Find(trueParent, graph.Edges.ElementAt(i).Item1);
|
|
int y = Find(trueParent, graph.Edges.ElementAt(i).Item2);
|
|
|
|
if (x == y)
|
|
return true;
|
|
|
|
Union(trueParent, x, y);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public Graph<U> Morph<U>(Func<T, U> vertices)
|
|
{
|
|
var result = new Graph<U>() { Edges = Edges };
|
|
|
|
result.Vertices.AddRange(Vertices.Select(vertices));
|
|
|
|
return result;
|
|
}
|
|
|
|
public Graph<U, E> Morph<U, E>(Func<T, U> vertices, Func<(int, int), E> edges)
|
|
{
|
|
var result = new Graph<U, E>() { Edges = Edges };
|
|
|
|
result._edgeData = Edges.ToDictionary(k => k, v => edges(v));
|
|
result.Vertices.AddRange(Vertices.Select(vertices));
|
|
|
|
return result;
|
|
}
|
|
|
|
public IEnumerable<int> Neighbours(int vertex)
|
|
{
|
|
if (!_edges.ContainsKey(vertex)) return Enumerable.Empty<int>();
|
|
|
|
return _edges[vertex];
|
|
}
|
|
}
|
|
|
|
public class Graph<T, E> : Graph<T>
|
|
{
|
|
internal Dictionary<(int, int), E> _edgeData = new Dictionary<(int, int), E>();
|
|
|
|
public void AddEdge(int a, int b, E data)
|
|
{
|
|
AddEdge(a, b);
|
|
SetEdgeData((a, b), data);
|
|
}
|
|
|
|
public void SetEdgeData((int, int) edge, E data)
|
|
{
|
|
var (a, b) = edge;
|
|
|
|
if (a > b) (a, b) = (b, a);
|
|
|
|
_edgeData[(a, b)] = data;
|
|
}
|
|
|
|
public E GetEdgeData((int, int) edge)
|
|
{
|
|
var (a, b) = edge;
|
|
|
|
if (a > b) (a, b) = (b, a);
|
|
|
|
return _edgeData[(a, b)];
|
|
}
|
|
|
|
public Graph<U, E2> Morph<U, E2>(Func<T, U> vertices, Func<E, (int, int), E2> edges)
|
|
{
|
|
var result = new Graph<U, E2>() { Edges = Edges };
|
|
|
|
result._edgeData = _edgeData.ToDictionary(e => e.Key, e => edges(e.Value, e.Key));
|
|
result.Vertices.AddRange(Vertices.Select(vertices));
|
|
|
|
return result;
|
|
}
|
|
}
|
|
} |