Advertisement
Guest User

Untitled

a guest
Mar 25th, 2017
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.49 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using ASD.Graphs;
  7.  
  8. namespace ASD
  9. {
  10.     public static class MatchingGraphExtender
  11.     {
  12.         /// <summary>
  13.         /// Podział grafu na cykle. Zakładamy, że dostajemy graf nieskierowany i wszystkie wierzchołki grafu mają parzyste stopnie
  14.         /// (nie trzeba sprawdzać poprawności danych).
  15.         /// </summary>
  16.         /// <param name="G">Badany graf</param>
  17.         /// <returns>Tablica cykli; krawędzie każdego cyklu powinny być uporządkowane zgodnie z kolejnością na cyklu, zaczynając od dowolnej</returns>
  18.         /// <remarks>
  19.         /// Metoda powinna działać w czasie O(m)
  20.         /// </remarks>
  21.         public static Edge[][] cyclePartition(this Graph g)
  22.         {
  23.             bool[] visited = new bool[g.VerticesCount];
  24.             int[] from = new int[g.VerticesCount];
  25.             bool[,] delEdges = new bool[g.VerticesCount, g.VerticesCount];
  26.             int edgesLeft = g.EdgesCount;
  27.             int cur = 0;
  28.             Stack<int> s = new Stack<int>();
  29.             List<Edge> edges = new List<Edge>();
  30.             List<List<Edge>> cycles = new List<List<Edge>>();
  31.             int cycleNum = 0;
  32.             int leavesCount = 0;
  33.             for (int i = 0; i < g.VerticesCount; i++)
  34.             {
  35.                 if (edgesLeft < 3)
  36.                     break;
  37.                 s.Clear();
  38.                 s.Push(i);
  39.                 for (int n = 0; n < visited.Length; n++)
  40.                 {
  41.                     visited[n] = false;
  42.                     from[n] = -1;
  43.                 }
  44.                 while (s.Count > 0)
  45.                 {
  46.                     cur = s.Peek();
  47.                     if (!visited[cur])
  48.                     {
  49.                         visited[cur] = true;
  50.                         from[cur] = cur;
  51.                     }
  52.                     leavesCount = 0;
  53.                     foreach (Edge e in g.OutEdges(cur))
  54.                     {
  55.                         if (delEdges[cur, e.To])
  56.                             continue;
  57.                         if(from[cur] != e.To)
  58.                             leavesCount++;
  59.                         if (visited[e.To] && from[cur] != e.To && !delEdges[cur,e.To])
  60.                         {
  61.                             int headC = e.To, fromHeadC = from[e.To], curFrom = e.To, curTo = cur, peeked = cur;
  62.                             do
  63.                             {
  64.                                 peeked = s.Pop();
  65.                                 if (peeked == curTo)
  66.                                     foreach (Edge ed in g.OutEdges(curFrom))
  67.                                     {
  68.                                         if (delEdges[ed.From, ed.To])
  69.                                             continue;
  70.                                         if (ed.To == curTo)
  71.                                         {
  72.                                             edges.Add(ed);
  73.                                             delEdges[ed.From, ed.To] = true;
  74.                                             delEdges[ed.To, ed.From] = true;
  75.                                             edgesLeft--;
  76.                                             curFrom = curTo;
  77.                                             curTo = from[curTo];
  78.                                             break;
  79.                                         }
  80.                                     }
  81.                                 visited[peeked] = false;
  82.                                 from[peeked] = -1;
  83.                             } while (peeked != fromHeadC);
  84.                             visited[headC] = false;
  85.                             from[headC] = -1;
  86.                             foreach (Edge ed in g.OutEdges(fromHeadC))
  87.                             {
  88.                                 if (delEdges[ed.From, ed.To])
  89.                                     continue;
  90.                                 if (ed.To == headC)
  91.                                 {
  92.                                     edges.Add(ed);
  93.                                     edgesLeft--;
  94.                                     delEdges[ed.From, ed.To] = true;
  95.                                     delEdges[ed.To, ed.From] = true;
  96.                                     break;
  97.                                 }
  98.                             }
  99.                             List<Edge> tmp = new List<Edge>();
  100.                             foreach (Edge t in edges)
  101.                                 tmp.Add(t);
  102.                             cycles.Add(tmp);
  103.                             edges.Clear();
  104.                             cycleNum++;
  105.                             break;
  106.                         }
  107.                         else
  108.                         {
  109.                             visited[e.To] = true;
  110.                             if (from[e.To] == -1)
  111.                             {
  112.                                 s.Push(e.To);
  113.                                 from[e.To] = cur;
  114.                             }
  115.                         }
  116.                     }
  117.                     if (leavesCount < 1)
  118.                         s.Pop();
  119.                 } //!while
  120.             }
  121.             if (cycleNum == 0)
  122.                 return null;
  123.             Edge[][] retList = new Edge[cycleNum][];
  124.             for (int i = 0; i < cycles.Count; i++)
  125.             {
  126.                 retList[i] = cycles[i].ToArray();
  127.             }
  128.             return retList;
  129.         }
  130.  
  131.         /// <summary>
  132.         /// Szukanie skojarzenia doskonałego w grafie nieskierowanym o którym zakładamy, że jest dwudzielny i 2^r-regularny
  133.         /// (nie trzeba sprawdzać poprawności danych)
  134.         /// </summary>
  135.         /// <param name="G">Badany graf</param>
  136.         /// <returns>Skojarzenie doskonałe w G</returns>
  137.         /// <remarks>
  138.         /// Metoda powinna działać w czasie O(m), gdzie m jest liczbą krawędzi grafu G
  139.         /// </remarks>
  140.         public static Graph perfectMatching(this Graph G)
  141.         {
  142.             int r = (int)Math.Log(G.OutDegree(0), 2);
  143.             for(int n = 0; n < r; n++)
  144.             {
  145.                 Edge[][] cycles = cyclePartition(G);
  146.                 if (cycles == null)
  147.                     return G;
  148.                 for (int i = 0; i < cycles.GetLength(0); i++)
  149.                     for (int j = 0; j < cycles[i].Length; j += 2)
  150.                     {
  151.                         G.DelEdge(cycles[i][j]);
  152.                     }
  153.             }
  154.             return G;
  155.         }
  156.     }
  157. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement