inz-00/Assets/Scripts/Common/Graph.cs

167 lines
4.3 KiB
C#

using Assets.Common;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Assets.Common
{
[Serializable]
public class Graph<T> : ICloneable
{
public List<T> Vertices { get; internal set; } = new List<T>();
private Dictionary<int, List<int>> _edges = new Dictionary<int, List<int>>();
public T this[int i] => Vertices[i];
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];
}
virtual public object Clone()
{
return Morph(l => l);
}
}
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;
}
public override object Clone()
{
return Morph(l => l, l => l);
}
}
}