Advertisement
myloyo

графы 3

May 18th, 2024
847
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 22.78 KB | None | 0 0
  1. // класс городов
  2.  
  3. using System;
  4.  
  5. namespace Myloyorrrr
  6. {
  7.     internal class GorodaOnline
  8.     {
  9.         public string Name { get; set; }
  10.         public int X { get; set; }
  11.         public int Y { get; set; }
  12.        
  13.         public GorodaOnline(string name, int x, int y)
  14.         {
  15.             Name = name;
  16.             X = x;
  17.             Y = y;
  18.         }
  19.         public double Distance(GorodaOnline a)
  20.         {
  21.             return Math.Sqrt((this.X - a.X) * (this.X - a.X) + (this.Y - a.Y) * (this.Y - a.Y));
  22.         }
  23.  
  24.         public override string ToString()
  25.         {
  26.             return Name + " " + X + " " + Y;
  27.         }
  28.  
  29.     }
  30. }
  31.  
  32. // класс графов
  33.  
  34. using System;
  35. using System.Collections;
  36. using System.Collections.Generic;
  37. using System.IO;
  38.  
  39. namespace Myloyorrrr
  40. {
  41.     public class Graph
  42.     {
  43.         private class Node //вложенный класс для скрытия данных и алгоритмов
  44.         {
  45.             private double[,] array; //матрица смежности
  46.             public double this[int i, int j] //индексатор для обращения к матрице смежности
  47.             {
  48.                 get
  49.                 {
  50.                     return array[i, j];
  51.                 }
  52.                 set
  53.                 {
  54.                     array[i, j] = value;
  55.                 }
  56.             }
  57.             public int Size //свойство для получения размерности матрицы смежности
  58.             {
  59.                 get
  60.                 {
  61.                     return array.GetLength(0);
  62.                 }
  63.             }
  64.             private bool[] nov; //вспомогательный массив: если i-ый элемент массива равен
  65.                                 //true, то i-ая вершина еще не просмотрена; если i-ый
  66.                                 //элемент равен false, то i-ая вершина просмотрена
  67.             public void NovSet() //метод помечает все вершины графа как непросмотреные
  68.             {
  69.                 for (int i = 0; i < Size; i++)
  70.                 {
  71.                     nov[i] = true;
  72.                 }
  73.             }
  74.             //конструктор вложенного класса, инициализирует матрицу смежности и
  75.             // вспомогательный массив
  76.             public Node(double[,] a)
  77.             {
  78.                 array = a;
  79.                 nov = new bool[a.GetLength(0)];
  80.            
  81.             }
  82.  
  83.             public void Add(int a, int b)
  84.             {
  85.                 if (a >= 0 && a < Size && b >= 0 && b < Size)
  86.                 {
  87.                     //array[a - 1, b - 1] = 1; // Для орграфа
  88.                     array[b - 1, a - 1] = 1; // Для неорграфа
  89.                 }
  90.                 else
  91.                 {
  92.                     Console.WriteLine("Некорректные вершины");
  93.                 }
  94.             }
  95.  
  96.             //реализация алгоритма обхода графа в глубину
  97.             public void Dfs(int v)
  98.             {
  99.                 Console.Write("{0} ", v); //просматриваем текущую вершину
  100.                 nov[v] = false; //помечаем ее как просмотренную
  101.                                 // в матрице смежности просматриваем строку с номером v
  102.                 for (int u = 0; u < Size; u++)
  103.                 {
  104.                     //если вершины v и u смежные, к тому же вершина u не просмотрена,
  105.                     if (array[v, u] != 0 && nov[u])
  106.                     {
  107.                         Dfs(u); // то рекурсивно просматриваем вершину
  108.                     }
  109.                 }
  110.             }
  111.             //реализация алгоритма обхода графа в ширину
  112.             public void Bfs(int v)
  113.             {
  114.                 Queue q = new Queue(); // инициализируем очередь
  115.                 q.Add(v); //помещаем вершину v в очередь
  116.                 nov[v] = false; // помечаем вершину v как просмотренную
  117.                 while (!q.IsEmpty) // пока очередь не пуста
  118.                 {
  119.                     v = (int)q.Take(); //извлекаем вершину из очереди
  120.                     Console.Write("{0} ", v); //просматриваем ее
  121.                     for (int u = 0; u < Size; u++) //находим все вершины
  122.                     {
  123.                         if (array[v, u] != 0 && nov[u]) // смежные с данной и еще не просмотренные
  124.                         {
  125.                             q.Add(u); //помещаем их в очередь
  126.                             nov[u] = false; //и помечаем как просмотренные
  127.                         }
  128.                     }
  129.                 }
  130.             }
  131.             //реализация алгоритма Дейкстры
  132.             public double[] Dijkstr(int v, int nz, out int[] p)
  133.             {
  134.                 //создаем матрицы d и p
  135.                 double[] d = new double[Size]; // массив расстояний
  136.                 p = new int[Size]; // массив предыдущих вершин путей
  137.                
  138.                 for (int u = 0; u < Size; u++)
  139.                 {
  140.                     d[u] = int.MaxValue;
  141.                     p[u] = -1;
  142.                 }
  143.                 d[v] = 0;
  144.                 nov[nz] = false; //не ходим в город ненужный
  145.  
  146.                 for (int i = 0; i < Size-1; i++)
  147.                 {
  148.                     // выбираем из множества V\S такую вершину w, что D[w] минимально
  149.                     double min = int.MaxValue;
  150.                     int w = 0;
  151.                     for (int u = 0; u < Size; u++)
  152.                     {
  153.                         if (nov[u] && min > d[u])
  154.                         {
  155.                             min = d[u];
  156.                             w = u;
  157.                         }
  158.                     }
  159.  
  160.                     nov[w] = false; //помещаем w в множество S
  161.                                     //для каждой вершины из множества V\S определяем кратчайший путь от
  162.                                     // источника до этой вершины
  163.                     for (int u = 0; u < Size; u++)
  164.                     {
  165.                         double distance = d[w] + array[w, u];
  166.                         if (nov[u] && d[u] > distance && array[w, u] != 0)
  167.                         {
  168.                             d[u] = distance;
  169.                             p[u] = w;
  170.                         }
  171.                     }
  172.                 }
  173.                 return d; //в качестве результата возвращаем массив кратчайших путей для
  174.             }
  175.             //заданного источника
  176.             //восстановление пути от вершины a до вершины b для алгоритма Дейкстры
  177.             //public void WayDijkstr(int a, int b, double[] p, ref Stack items)
  178.             //{
  179.             //    items.Push(b); //помещаем вершину b в стек
  180.             //    if (a == p[b]) //если предыдущей для вершины b является вершина а, то
  181.             //    {
  182.             //        items.Push(a); //помещаем а в стек и завершаем восстановление пути
  183.             //    }
  184.             //    else //иначе метод рекурсивно вызывает сам себя для поиска пути
  185.             //    { //от вершины а до вершины, предшествующей вершине b
  186.             //        WayDijkstr(a, p[b], p, ref items);
  187.             //    }
  188.             //}
  189.  
  190.             //реализация алгоритма Флойда
  191.             public double[,] Floyd(out int[,] p)
  192.             {
  193.                 int i, j, k;
  194.                 //создаем массивы р и а
  195.                 double[,] a = new double[Size, Size];
  196.                 p = new int[Size, Size];
  197.                 for (i = 0; i < Size; i++)
  198.                 {
  199.                     for (j = 0; j < Size; j++)
  200.                     {
  201.                         if (i == j)
  202.                         {
  203.                             a[i, j] = 0;
  204.                         }
  205.                         else
  206.                         {
  207.                             if (array[i, j] == 0)
  208.                             {
  209.                                 a[i, j] = int.MaxValue;
  210.                             }
  211.                             else
  212.                             {
  213.                                 a[i, j] = array[i, j];
  214.                             }
  215.                         }
  216.                         p[i, j] = -1;
  217.                     }
  218.                 }
  219.                 //осуществляем поиск кратчайших путей
  220.                 for (k = 0; k < Size; k++)
  221.                 {
  222.                     for (i = 0; i < Size; i++)
  223.                     {
  224.                         for (j = 0; j < Size; j++)
  225.                         {
  226.                             double distance = a[i, k] + a[k, j];
  227.                             if (a[i, j] > distance)
  228.                             {
  229.                                 a[i, j] = distance;
  230.                                 p[i, j] = k;
  231.                             }
  232.                         }
  233.                     }
  234.                 }
  235.                 return a;//в качестве результата возвращаем массив кратчайших путей между
  236.             }
  237.  
  238.             //восстановление пути от вершины a до вершины в для алгоритма Флойда
  239.             public void WayFloyd(int a, int b, int[,] p, ref Queue items)
  240.             {
  241.                 int k = p[a, b];
  242.                 //если k<> -1, то путь состоит более чем из двух вершин а и b, и проходит через
  243.                 //вершину k, поэтому
  244.                 if (k != -1)
  245.                 {
  246.                     // рекурсивно восстанавливаем путь между вершинами а и k
  247.                     WayFloyd(a, k, p, ref items);
  248.                     items.Add(k); //помещаем вершину к в очередь
  249.                                   // рекурсивно восстанавливаем путь между вершинами k и b
  250.                     WayFloyd(k, b, p, ref items);
  251.                 }
  252.             }
  253.         }
  254.        
  255.         //конец вложенного клаcса
  256.         private Node graph; //закрытое поле, реализующее АТД «граф»
  257.         private List<GorodaOnline> l;
  258.         public Graph(string name) //конструктор внешнего класса
  259.         {
  260.             using (StreamReader file = new StreamReader(name))
  261.             {
  262.                 int n = int.Parse(file.ReadLine());
  263.                 l = new List<GorodaOnline>();
  264.                 for (int i = 0; i<n; i++)
  265.                 {
  266.                     string line = file.ReadLine();
  267.                     string[] mas = line.Split(' ');
  268.                     l.Add(new GorodaOnline(mas[0], int.Parse(mas[1]), int.Parse(mas[2])));
  269.                 }
  270.  
  271.                 double[,] a = new double[n, n];
  272.                 for (int i = 0; i < n; i++)
  273.                 {
  274.                     string line = file.ReadLine();
  275.                     string[] mas = line.Split(' ');
  276.                     for (int j = 0; j < n; j++)
  277.                     {
  278.                         int b = int.Parse(mas[j]);
  279.                         a[i, j] = l[i].Distance(l[j]) * b;
  280.                     }
  281.                 }
  282.                 graph = new Node(a);
  283.             }
  284.         }
  285.         //метод выводит матрицу смежности на консольное окно
  286.         public void Show()
  287.         {
  288.             foreach(GorodaOnline gorod in l)
  289.             {
  290.                 Console.WriteLine(gorod);
  291.             }
  292.             for (int i = 0; i < graph.Size; i++)
  293.             {
  294.                 for (int j = 0; j < graph.Size; j++)
  295.                 {
  296.                     if (graph[i, j] == 0)
  297.                     {
  298.                         Console.Write("{0}\t", graph[i, j]);
  299.                     }
  300.                     else
  301.                     {
  302.                         Console.Write("{0:f2}\t", graph[i, j]);
  303.                     }
  304.                 }
  305.                 Console.WriteLine();
  306.             }
  307.         }
  308.         public void Add(int a, int b)
  309.         {
  310.             graph.Add(a, b);
  311.         }
  312.         public void Dfs(int v)
  313.         {
  314.             graph.NovSet();//помечаем все вершины графа как непросмотренные
  315.             graph.Dfs(v); //запускаем алгоритм обхода графа в глубину
  316.             Console.WriteLine();
  317.         }
  318.         public void Bfs(int v)
  319.         {
  320.             graph.NovSet();//помечаем все вершины графа как непросмотренные
  321.             graph.Bfs(v); //запускаем алгоритм обхода графа в ширину
  322.             Console.WriteLine();
  323.         }
  324.         public void Dijkstr(int v, int nz)
  325.         {
  326.             graph.NovSet();//помечаем все вершины графа как непросмотренные
  327.             int[] p;
  328.             double[] d = graph.Dijkstr(v, nz, out p); //запускаем алгоритм Дейкстры
  329.                                                 //анализируем полученные данные и выводим их на экран
  330.             Console.WriteLine("Длина кратчайшие пути от вершины {0} до вершины", v);
  331.  
  332.             for (int i = 0; i < graph.Size; i++)
  333.             {
  334.                 if (i != v)
  335.                 {
  336.                     Console.Write("{0} равна {1}, ", i, d[i]);
  337.                     Console.Write("путь ");
  338.                     if (d[i] != int.MaxValue)
  339.                     {
  340.                         Stack items = new Stack();
  341.                         //graph.WayDijkstr(v, i, p, ref items);
  342.                         while (items.Peek()!= null)
  343.                         {
  344.                             Console.Write("{0} ", items.Pop());
  345.                         }
  346.                     }
  347.  
  348.                 }
  349.                 Console.WriteLine();
  350.             }
  351.         }
  352.         public void Myloyo_find(int a, int b, int nz)
  353.         {
  354.             graph.NovSet();//помечаем все вершины графа как непросмотренные
  355.             int[] p;
  356.             double[] d = graph.Dijkstr(a, nz, out p); //запускаем алгоритм Дейкстры
  357.                                                       //анализируем полученные данные и выводим их на экран
  358.             if (d[b]!= int.MaxValue)
  359.             {
  360.                 Console.WriteLine("Длина кратчайшего пути из города {0} в город {1} без города {2} равен {3}", l[a].Name, l[b].Name, l[nz].Name, d[b]);
  361.                 Console.WriteLine();
  362.                 List<int>path = new List<int>();
  363.                 int cur = b;
  364.                 while (cur != -1)
  365.                 {
  366.                     path.Add(cur);
  367.                     cur = p[cur];
  368.                 }
  369.  
  370.                 path.Reverse();
  371.                 Console.WriteLine($"Путь из города {l[a].Name} в город {l[b].Name} без города {l[nz].Name}:");
  372.                 foreach(int i in path){
  373.                     Console.Write(l[i].Name + ", ");
  374.                 }
  375.                 Console.WriteLine();
  376.             }
  377.             else
  378.             {
  379.                 Console.WriteLine($"Пути из {l[a].Name} в {l[b].Name} нет. (точка точка точка)");
  380.             }
  381.         }
  382.         public void Floyd()
  383.         {
  384.             int[,] p;
  385.             double[,] a = graph.Floyd(out p); //запускаем алгоритм Флойда
  386.             int i, j;
  387.             //анализируем полученные данные и выводим их на экран
  388.             for (i = 0; i < graph.Size; i++)
  389.             {
  390.                 for (j = 0; j < graph.Size; j++)
  391.                 {
  392.                     if (i != j)
  393.                     {
  394.                         if (a[i, j] == int.MaxValue)
  395.                         {
  396.                             Console.WriteLine("Пути из города {0} в город {1} не существует", i, j);
  397.                         }
  398.                         else
  399.                         {
  400.                             Console.Write("Кратчайший путь из города {0} до города {1} равен {2}, ", i, j, a[i,j]);
  401.                             Console.Write(" путь ");
  402.                             Queue items = new Queue();
  403.                             items.Add(i);
  404.                             graph.WayFloyd(i, j, p, ref items);
  405.                             items.Add(j);
  406.                             while (!items.IsEmpty)
  407.                             {
  408.                                 Console.Write("{0} ", items.Take());
  409.                             }
  410.                             Console.WriteLine();
  411.                         }
  412.                     }
  413.                 }
  414.             }
  415.         }
  416.         public void Adjacent(int v) // 1 задача
  417.         {
  418.             Console.Write("Количество вершин смежных с {0} вершиной: ", v);
  419.             int counter = 0;
  420.             //просматриваем строку с номером v в матрице смежности
  421.             for (int i = 0; i < graph.Size; i++)
  422.             {
  423.                 if (graph[v-1, i] != 0)
  424.                 {
  425.                     counter++;
  426.                 }
  427.             }
  428.             Console.WriteLine(counter);
  429.         }
  430.         public void Floyd_new(int L)
  431.         {
  432.             int[,] p;
  433.             double[,] a = graph.Floyd(out p); //запускаем алгоритм Флойда
  434.             for(int x = 0; x < a.GetLength(0); x++)
  435.             {
  436.                 for(int y = 0; y < a.GetLength(1); y++)
  437.                 {
  438.                     Console.Write(a[x, y] + " ");
  439.                    
  440.                 }
  441.                 Console.WriteLine();
  442.             }
  443.  
  444.             int i, j;
  445.             //анализируем полученные данные и выводим их на экран
  446.             for (i = 0; i < graph.Size; i++)
  447.             {
  448.                 for (j = 0; j < graph.Size; j++)
  449.                 {
  450.                     if (i != j)
  451.                     {
  452.                         if (a[i, j] == int.MaxValue)
  453.                         {
  454.                             Console.WriteLine("Пути из вершины {0} в вершину {1} не существует", i, j);
  455.                         }
  456.                         else
  457.                         {
  458.                             if (a[i, j] <= L)
  459.                             {
  460.                                 Console.WriteLine("Пара вершин: {0} и {1}. Кратчайший путь равен {2}.", i, j, a[i, j]);
  461.                             }
  462.                             Queue items = new Queue();
  463.                             items.Add(i);
  464.                             graph.WayFloyd(i, j, p, ref items);
  465.                             items.Add(j);
  466.                         }
  467.                     }
  468.                 }
  469.             }
  470.         }
  471.     }
  472. }
  473.  
  474. // основная прога
  475.  
  476. using System;
  477.  
  478. namespace Myloyorrrr
  479. {
  480.     internal class Program
  481.     {
  482.         static void Main()
  483.         {
  484.  
  485.             Graph G = new Graph("C:/Настя/книит/in.txt");
  486.             G.Show();
  487.             Console.WriteLine();
  488.             Console.WriteLine("Введите первую вершину:");
  489.             int a = int.Parse(Console.ReadLine());
  490.             Console.WriteLine("Введите вторую вершину:");
  491.             int b = int.Parse(Console.ReadLine());
  492.             Console.WriteLine("Введите вершину, через которую нельзя пройти:");
  493.             int d = int.Parse(Console.ReadLine());
  494.             Console.WriteLine();
  495.             G.Myloyo_find(a-1, b-1, d-1);
  496.  
  497.  
  498.             //// 1 задача: подсчитать смежные вершины с данной вершиной
  499.             //Console.Write("Введите номер вершины: ");
  500.             //int v = int.Parse(Console.ReadLine());
  501.             //G.Adjacent(v);
  502.  
  503.             //// 2 задача: определить все пары вершин, для которых существует путь длиной не более L
  504.             //Console.Write("Введите требуемую длину пути: ");
  505.             //int L = int.Parse(Console.ReadLine());
  506.             //G.Floyd_new(L);
  507.  
  508.             //BinaryTree lipa = new BinaryTree();
  509.             //int n = 0;
  510.  
  511.             ////Чтение последовательности чисел из файла input.txt и добавление их в дерево
  512.             //using (StreamReader f = new StreamReader("C:/Настя/книит/in.txt"))
  513.             //{
  514.             //    string line;
  515.             //    while ((line = f.ReadLine()) != null)
  516.             //    {
  517.             //        string[] text = line.Split(' ');
  518.             //        for (int i = 0; i < text.Length; i++)
  519.             //        {
  520.             //            int num = int.Parse(text[i]);
  521.             //            lipa.Add(num);
  522.             //            n++;
  523.             //        }
  524.             //    }
  525.  
  526.             //}
  527.  
  528.             //lipa.Preorder();
  529.  
  530.             ////3 деревья
  531.             //bool IsBalance = lipa.Balance();
  532.             //if (IsBalance)
  533.             //{
  534.             //    Console.WriteLine("Дерево является сбалансированным");
  535.             //}
  536.             //else
  537.             //{
  538.             //    Console.WriteLine("Дерево не является сбалансированным");
  539.             //}
  540.         }
  541.     }
  542. }
  543.  
  544.  
  545.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement