using Assets.Common; using System; using System.Collections.Generic; using System.Linq; namespace Assets.Common { [Serializable] public class Graph : ICloneable { public List Vertices { get; internal set; } = new List(); private Dictionary> _edges = new Dictionary>(); 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>(); foreach (var (a, b) in value) AddEdge(a, b); } } public void AddEdge(int a, int b) { if (!_edges.ContainsKey(a)) _edges[a] = new List(); if (!_edges.ContainsKey(b)) _edges[b] = new List(); _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 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 Morph(Func vertices) { var result = new Graph() { Edges = Edges }; result.Vertices.AddRange(Vertices.Select(vertices)); return result; } public Graph Morph(Func vertices, Func<(int, int), E> edges) { var result = new Graph() { Edges = Edges }; result._edgeData = Edges.ToDictionary(k => k, v => edges(v)); result.Vertices.AddRange(Vertices.Select(vertices)); return result; } public IEnumerable Neighbours(int vertex) { if (!_edges.ContainsKey(vertex)) return Enumerable.Empty(); return _edges[vertex].Distinct(); } public virtual object Clone() { return Morph(l => l); } } public class Graph : Graph { 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 Morph(Func vertices, Func edges) { var result = new Graph() { 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); } } }