-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram
More file actions
210 lines (194 loc) · 8.61 KB
/
Copy pathProgram
File metadata and controls
210 lines (194 loc) · 8.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Threading;
using System.IO;
namespace Graphs
{
public static class Match
{
public static double degtorad(double deg)//градусы в радианы
{
return deg * Math.PI / 180;
}
public static double radtodeg(double rad)//радианы в градусы
{
return rad / Math.PI * 180;
}
public static double lengthdir_x(double len, double dir)//расстояние по X при передвижении по направлению
{
return len * Math.Cos(degtorad(dir));
}
public static double lengthdir_y(double len, double dir)//расстояние по Y при передвижении по направлению
{
return len * Math.Sin(degtorad(dir)) * (-1);
}
public static double point_direction(int x1, int y1, int x2, int y2)//угол направления между двумя точками
{
return 180 - radtodeg(Math.Atan2(y1 - y2, x1 - x2));
}
public static double point_distance(int x1, int y1, int x2, int y2)//расстояние между двумя точками
{
return Math.Sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
}
public class Graph
{
public class Node
{
public int id;//уникальный идентификатор узла
public int active;//статус обработки узла
public int x;//координаты
public int y;//для отрисовки вершины
public string name;//отображаемое имя
public List<int> edges;//список смежности
public void AddEdge(int id)
{
if (!edges.Contains(id)) edges.Add(id);//добавить узел в список смежности если его там не было
}
public void RemoveEdge(int id)
{
edges.Remove(id);//удаление узла из списка смежности
}
};
public List<Node> nodes = new List<Node>();//узлы графа
private int maxid = 0;//для запоминания уникальных идентификаторов
public List<int> used=new List<int>(4);//для проверки вершин на наличие циклов
public List<int> p= new List<int>(4);//массив предков для обхода
public List<Node> ans;//для топологической сортировки
public bool cycle = false;
public int x = 0;//координаты
public int y = 0;//появления новых узлов
public int sz = 32;//размер узлов (для отрисовки)
public Graph()
{ }
public Graph(string f)
{
string[] F = File.ReadAllLines(f);
foreach (string S in F)//читать все строки из файла
{
string[] SS = S.Split(',');//разделить строку (ожидается 4 элемента)
List<int> L = new List<int>();//пустой список смежности
if (SS[3] != "")
{
string[] SSE = SS[3].Split(';');//отдельно разделить список смежности из файла на строки
foreach (string eg in SSE)
L.Add(int.Parse(eg));//заполнение списка смежности
}
LoadNode(int.Parse(SS[0]), int.Parse(SS[1]), int.Parse(SS[2]), SS[4], L);//добавить загруженный узел в граф
}
}
public void AddNode(string name)//добавление узла в граф
{
bool find = false;//найдено пустое место между 0 и максимальным известным идентификатором
int id = 0;//новый уникальный идентификатор
for (int i = 0; i < maxid; i++)//проверить для всех идентификаторов от 0 до максимального
{
bool exist = false;//такой идентификатор уже существует
foreach (Node nd in nodes)
{
if (nd.id == i)
{
exist = true;//найден указанный идентификатор
break;
}
}
if (!exist)//если не существует указанный идентификатор, то
{
id = i;//на его место
find = true;//можно поместить новый узел
break;
}
}
if (!find)//если пустое место не найдено
{
id = maxid;
maxid++;//просто добавить в конец
}
Node n = new Node();
n.id = id;
n.active = 0;
n.x = x;
n.y = y;
//все параметры задаются по умолчанию
if (name != "")
n.name = name;
else
n.name = id.ToString();//если имя не указано, то прописать туда идентификатор
n.edges = new List<int>();//пустой список смежности
nodes.Add(n);
nodes.Sort((x, y) => x.id.CompareTo(y.id));//сортировка по идентификатору для оптимизации
}
public void RemoveNode(int id)//удаление узла из графа
{
Node n = null;
foreach (Node nd in nodes)
{
nd.edges.Remove(id);//удалить узел из списков смежности у всех других узлов
if (nd.id == id)
{
n = nd;//найти сам удаляемый узел
}
}
nodes.Remove(n);
}
public void LoadNode(int id, int x, int y, string name, List<int> e)//добавление узла при загрузке из файла
{
Node n = new Node();
if (maxid <= id)
maxid = id + 1;//запомнить новый максимальный идентификатор
n.id = id;
n.active = 0;
n.x = x;
n.y = y;
if (name != "")
n.name = name;
else
n.name = id.ToString();
n.edges = e;
//все параметры, необходимые для создания узла, передаются в функцию, включая список смежности
nodes.Add(n);
nodes.Sort((xx, yy) => xx.id.CompareTo(yy.id));
}
public void Circle(Node m)
{
used[nodes.IndexOf(m)] = 1;
for (int i = 0; i < m.edges.Count; i++)
foreach (Node n in nodes)
if (n.id == m.edges[i]) {
if (used[nodes.IndexOf(n)] == 0)
{
p[nodes.IndexOf(n)] = nodes.IndexOf(m);
Circle(n);
}
else if (used[nodes.IndexOf(n)] == 1 && p[nodes.IndexOf(n)]!= nodes.IndexOf(m))
cycle = true;
break;
}
used[nodes.IndexOf(m)] = 2;
}
public void TopSort(Node m)
{
if (used[nodes.IndexOf(m)] == 0)
{
used[nodes.IndexOf(m)] = 2;
m.active = 1;
//Thread.Sleep(500);
ans.Add(m);
foreach (Node n in nodes)
if (m.edges.IndexOf(n.id) != -1)
TopSort(n);
}
}
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}