View difference between Paste ID: NKDAbiED and gfR6HN51
SHOW: | | - or go back to the newest paste.
1
///////////////////////////////////
2
//            Graph.h            //
3
///////////////////////////////////
4
5
#pragma once
6
#include <iostream>
7
#include <iomanip>
8
#include <fstream>
9
#include <vector>
10
#include <map>
11
using namespace std;
12
13
/// <summary>
14
/// Граф 
15
/// </summary>
16
/// <typeparam name="Vertice"> тип вершин графа </typeparam>
17
/// <typeparam name="Edge"> тип ребер графа (int по умолчанию) </typeparam>
18
template <class Vertice, class Edge = int>
19-
	/// <summary>
19+
20-
	/// Количество вершин и ребер в графе
20+
21-
	/// </summary>
21+
    /// <summary>
22-
	int _N = 0, _M = 0;
22+
    /// Количество вершин и ребер в графе
23
    /// </summary>
24-
	/// <summary>
24+
    int _N = 0, _M = 0;
25-
	/// Критерий ориентированности и взвешенности графа 
25+
26-
	/// </summary>
26+
    /// <summary>
27-
	bool IsDirected = false, IsWeighted = false;
27+
    /// Критерий ориентированности и взвешенности графа 
28
    /// </summary>
29-
	/// <summary>
29+
    bool IsDirected = false, IsWeighted = false;
30-
	/// Список смежности графа 
30+
31-
	/// </summary>
31+
    /// <summary>
32-
	map <Vertice, map<Vertice, Edge>> graph;
32+
    /// Список смежности графа 
33
    /// </summary>
34
    map <Vertice, map<Vertice, Edge>> graph;
35
36-
	/// <summary>
36+
37-
	/// Конструктор по умолчанию
37+
38-
	/// </summary>
38+
    /// <summary>
39-
	Graph() {};
39+
    /// Конструктор по умолчанию
40
    /// </summary>
41-
	/// <summary>
41+
    Graph() {};
42-
	/// Конструктор, создающий пустой граф, определяющий 
42+
43-
	/// ориентированность и взвешенность графа 
43+
    /// <summary>
44-
	/// </summary>
44+
    /// Конструктор, создающий пустой граф, определяющий 
45-
	/// <param name="direction"> критерий ориентированности </param>
45+
    /// ориентированность и взвешенность графа 
46-
	/// <param name="weighting"> критерий взвешенности </param>
46+
    /// </summary>
47-
	Graph(string direction, string weighting)
47+
    /// <param name="direction"> критерий ориентированности </param>
48-
	{
48+
    /// <param name="weighting"> критерий взвешенности </param>
49-
		if (direction == "directed") IsDirected = true;
49+
    Graph(string direction, string weighting)
50-
		if (weighting == "weighted") IsWeighted = true;
50+
    {
51-
	}
51+
        if (direction == "directed") IsDirected = true;
52
        if (weighting == "weighted") IsWeighted = true;
53-
	/// <summary>
53+
    }
54-
	/// Конструктор, считывающий информацию из файла 
54+
55-
	/// или из консоли (stdin)
55+
    /// <summary>
56-
	/// </summary>
56+
    /// Конструктор, считывающий информацию из файла 
57-
	/// <param name="filePath"> путь к файлу или ключевое слово stdin </param>
57+
    /// или из консоли (stdin)
58-
	Graph(string filePath)
58+
    /// </summary>
59-
	{
59+
    /// <param name="filePath"> путь к файлу или ключевое слово stdin </param>
60-
		ifstream fin;
60+
    Graph(string filePath)
61
    {
62-
		if (filePath == "stdin") fin = ifstream(stdin);
62+
        ifstream fin;
63-
		else fin = ifstream(filePath);
63+
64
        if (filePath == "stdin") fin = ifstream(stdin);
65-
		string cmd, direction, weighting;
65+
        else fin = ifstream(filePath);
66-
		fin >> cmd >> direction >> weighting;
66+
67
        string cmd, direction, weighting;
68-
		*this = Graph(direction, weighting);
68+
        fin >> cmd >> direction >> weighting;
69
70-
		fin >> cmd >> _N;
70+
        *this = Graph(direction, weighting);
71
72-
		for (int i = 0; i < _N; ++i)
72+
        fin >> cmd >> _N;
73-
		{
73+
74-
			Vertice v; fin >> v;
74+
        for (int i = 0; i < _N; ++i)
75-
			graph.insert(pair<Vertice, map<Vertice, Edge>>(v, map<Vertice, Edge>()));
75+
        {
76-
		}
76+
            Vertice v; fin >> v;
77
            graph.insert(pair<Vertice, map<Vertice, Edge>>(v, map<Vertice, Edge>()));
78-
		fin >> cmd >> _M;
78+
        }
79
80-
		for (int i = 0; i < _M; ++i)
80+
        fin >> cmd >> _M;
81-
		{
81+
82-
			Vertice u, v; Edge w; fin >> u >> v;
82+
        for (int i = 0; i < _M; ++i)
83
        {
84-
			if (!IsWeighted) w = 1;
84+
            Vertice u, v; Edge w; fin >> u >> v;
85-
			else fin >> w;
85+
86
            if (!IsWeighted) w = 1;
87-
			graph[u].insert(pair<Vertice, Edge>(v, w));
87+
            else fin >> w;
88-
			if (!IsDirected) graph[v].insert(pair<Vertice, Edge>(u, w));
88+
89-
		}
89+
            graph[u].insert(pair<Vertice, Edge>(v, w));
90
            if (!IsDirected) graph[v].insert(pair<Vertice, Edge>(u, w));
91-
		if (filePath != "stdin") fin.close();
91+
        }
92-
	}
92+
93
        if (filePath != "stdin") fin.close();
94-
	/// <summary>
94+
    }
95-
	/// Количество вершин графа 
95+
96-
	/// </summary>
96+
    /// <summary>
97-
	/// <returns> количество вершин графа </returns>
97+
    /// Количество вершин графа 
98-
	int n() { return _N; }
98+
    /// </summary>
99
    /// <returns> количество вершин графа </returns>
100-
	/// <summary>
100+
    int n() { return _N; }
101-
	/// Количество ребер графа 
101+
102-
	/// </summary>
102+
    /// <summary>
103-
	/// <returns> количество ребер графа </returns>
103+
    /// Количество ребер графа 
104-
	int m() { return _M; }
104+
    /// </summary>
105
    /// <returns> количество ребер графа </returns>
106-
	/// <summary>
106+
    int m() { return _M; }
107-
	/// Метод, выдающий информацию об
107+
108-
	/// ориентированности графа
108+
    /// <summary>
109-
	/// </summary>
109+
    /// Метод, выдающий информацию об
110-
	/// <returns> true, если граф ориентированный, иначе - false </returns>
110+
    /// ориентированности графа
111-
	bool isDirected() { return IsDirected; }
111+
    /// </summary>
112
    /// <returns> true, если граф ориентированный, иначе - false </returns>
113-
	/// <summary>
113+
    bool isDirected() { return IsDirected; }
114-
	/// Метод, выдающий информацию о
114+
115-
	/// взвешенности графа 
115+
    /// <summary>
116-
	/// </summary>
116+
    /// Метод, выдающий информацию о
117-
	/// <returns> true, если граф взвешенный, иначе - false </returns>
117+
    /// взвешенности графа 
118-
	bool isWeighted() { return IsWeighted; }
118+
    /// </summary>
119
    /// <returns> true, если граф взвешенный, иначе - false </returns>
120-
	/// <summary>
120+
    bool isWeighted() { return IsWeighted; }
121-
	/// Добавление вершины в граф 
121+
122-
	/// </summary>
122+
    /// <summary>
123-
	/// <param name="v"> добавляемая в граф вершина </param>
123+
    /// Метод, возращающий список смежности графа
124-
	void addVertice(Vertice v)
124+
    /// </summary>
125-
	{
125+
    /// <returns> список смежности графа </returns>
126-
		try
126+
    map<Vertice, map<Vertice, Edge>> edges() { return graph; }
127-
		{
127+
128-
			if (graph.find(v) != graph.end()) throw "Добавление вершины: заданная вершина уже есть в графе";
128+
    /// <summary>
129-
			else
129+
    /// Добавление вершины в граф 
130-
			{
130+
    /// </summary>
131-
				++_N;
131+
    /// <param name="v"> добавляемая в граф вершина </param>
132-
				graph.insert(pair<Vertice, map<Vertice, Edge>>(v, map<Vertice, Edge>()));
132+
    void addVertice(Vertice v)
133-
			}
133+
    {
134-
		}
134+
        try
135-
		catch (const char* msg)
135+
        {
136-
		{
136+
            if (graph.find(v) != graph.end()) throw "Добавление вершины: заданная вершина уже есть в графе";
137-
			cout << msg << "\n";
137+
            else
138-
		}
138+
            {
139-
	}
139+
                ++_N;
140
                graph.insert(pair<Vertice, map<Vertice, Edge>>(v, map<Vertice, Edge>()));
141-
	/// <summary>
141+
            }
142-
	/// Удаление вершины из графа 
142+
        }
143-
	/// </summary>
143+
        catch (const char* msg)
144-
	/// <param name="v"> удаляемая из графа вершина </param>
144+
        {
145-
	void removeVertice(Vertice v)
145+
            cout << msg << "\n";
146-
	{
146+
        }
147-
		try
147+
    }
148-
		{
148+
149-
			if (graph.find(v) == graph.end()) throw "Удаление вершины: в графе отсутствует заданная вершина";
149+
    /// <summary>
150-
			else
150+
    /// Удаление вершины из графа 
151-
			{
151+
    /// </summary>
152-
				--_N; _M -= graph[v].size();
152+
    /// <param name="v"> удаляемая из графа вершина </param>
153
    void removeVertice(Vertice v)
154-
				graph.erase(v);
154+
    {
155
        try
156-
				for (auto p : graph)
156+
        {
157-
					if (graph[p.first].find(v) != graph[p.first].end())
157+
            if (graph.find(v) == graph.end()) throw "Удаление вершины: в графе отсутствует заданная вершина";
158-
					{
158+
            else
159-
						if (IsDirected) --_M;
159+
            {
160-
						graph[p.first].erase(v);
160+
                --_N; _M -= graph[v].size();
161-
					}
161+
162-
			}
162+
                graph.erase(v);
163-
		}
163+
164-
		catch (const char* msg)
164+
                for (auto p : graph)
165-
		{
165+
                    if (graph[p.first].find(v) != graph[p.first].end())
166-
			cout << msg << "\n";
166+
                    {
167-
		}
167+
                        if (IsDirected) --_M;
168-
	}
168+
                        graph[p.first].erase(v);
169
                    }
170-
	/// <summary>
170+
            }
171-
	/// Добавление ребра в граф 
171+
        }
172-
	/// </summary>
172+
        catch (const char* msg)
173-
	/// <param name="u"> первая вершина ребра </param>
173+
        {
174-
	/// <param name="v"> вторая вершина ребра </param>
174+
            cout << msg << "\n";
175-
	/// <param name="w"> вес ребра (для невзвешенных графов w = 1) </param>
175+
        }
176-
	void addEdge(Vertice u, Vertice v, Edge w)
176+
    }
177-
	{
177+
178-
		try
178+
    /// <summary>
179-
		{
179+
    /// Добавление ребра в граф 
180-
			if (graph.find(u) == graph.end() || graph.find(v) == graph.end()) throw "Добавление ребра: в графе отсутствует(ют) заданная(ые) вершина(ы)";
180+
    /// </summary>
181-
			else if (!IsDirected && u == v) throw "Добавление ребра: невозможно добавить петлю в неориентированный граф";
181+
    /// <param name="u"> первая вершина ребра </param>
182-
			else if (graph[u].find(v) != graph[u].end()) throw "Добавление ребра: заданное ребро уже есть в графе";
182+
    /// <param name="v"> вторая вершина ребра </param>
183-
			else
183+
    /// <param name="w"> вес ребра (для невзвешенных графов w = 1) </param>
184-
			{
184+
    void addEdge(Vertice u, Vertice v, Edge w)
185-
				++_M;
185+
    {
186-
				graph[u][v] = w;
186+
        try
187-
				if (!IsDirected) graph[v][u] = w;
187+
        {
188-
			}
188+
            if (graph.find(u) == graph.end() || graph.find(v) == graph.end()) throw "Добавление ребра: в графе отсутствует(ют) заданная(ые) вершина(ы)";
189-
		}
189+
            else if (!IsDirected && u == v) throw "Добавление ребра: невозможно добавить петлю в неориентированный граф";
190-
		catch (const char* msg)
190+
            else if (graph[u].find(v) != graph[u].end()) throw "Добавление ребра: заданное ребро уже есть в графе";
191-
		{
191+
            else
192-
			cout << msg << "\n";
192+
            {
193-
		}
193+
                ++_M;
194-
	}
194+
                graph[u][v] = w;
195
                if (!IsDirected) graph[v][u] = w;
196-
	/// <summary>
196+
            }
197-
	/// Удаление ребра из графа 
197+
        }
198-
	/// </summary>
198+
        catch (const char* msg)
199-
	/// <param name="u"> первая вершина ребра </param>
199+
        {
200-
	/// <param name="v"> вторая вершина ребра </param>
200+
            cout << msg << "\n";
201-
	void removeEdge(Vertice u, Vertice v)
201+
        }
202-
	{
202+
    }
203-
		try
203+
204-
		{
204+
    /// <summary>
205-
			if (graph.find(u) == graph.end() || graph.find(v) == graph.end()) throw "Удаление ребра: в графе отсутствует(ют) заданная(ые) вершина(ы)";
205+
    /// Удаление ребра из графа 
206-
			else
206+
    /// </summary>
207-
			{
207+
    /// <param name="u"> первая вершина ребра </param>
208-
				if (graph[u].find(v) == graph[u].end()) throw "Удаление ребра: в графе отсутствует заданное ребро";
208+
    /// <param name="v"> вторая вершина ребра </param>
209-
				else
209+
    void removeEdge(Vertice u, Vertice v)
210-
				{
210+
    {
211-
					--_M;
211+
        try
212-
					graph[u].erase(v);
212+
        {
213-
					if (!IsDirected) graph[v].erase(u);
213+
            if (graph.find(u) == graph.end() || graph.find(v) == graph.end()) throw "Удаление ребра: в графе отсутствует(ют) заданная(ые) вершина(ы)";
214-
				}
214+
            else
215-
			}
215+
            {
216-
		}
216+
                if (graph[u].find(v) == graph[u].end()) throw "Удаление ребра: в графе отсутствует заданное ребро";
217-
		catch (const char* msg)
217+
                else
218-
		{
218+
                {
219-
			cout << msg << "\n";
219+
                    --_M;
220-
		}
220+
                    graph[u].erase(v);
221-
	}
221+
                    if (!IsDirected) graph[v].erase(u);
222
                }
223-
	/// <summary>
223+
            }
224-
	/// Очищение графа (ориентированность 
224+
        }
225-
	/// и взвешенность остаются прежними)
225+
        catch (const char* msg)
226-
	/// </summary>
226+
        {
227-
	void clear()
227+
            cout << msg << "\n";
228-
	{
228+
        }
229-
		_N = 0; _M = 0;
229+
    }
230-
		graph.clear();
230+
231-
	}
231+
    /// <summary>
232
    /// Очищение графа (ориентированность 
233-
	/// <summary>
233+
    /// и взвешенность остаются прежними)
234-
	/// Вывод информации о графе в файл или
234+
    /// </summary>
235-
	/// на консоль (stdout)
235+
    void clear()
236-
	/// </summary>
236+
    {
237-
	/// <param name="filePath"> путь к файлу или ключевое слово stdout </param>
237+
        _N = 0; _M = 0;
238-
	void print(string filePath)
238+
        graph.clear();
239-
	{
239+
    }
240-
		ofstream fout;
240+
241
    /// <summary>
242-
		if (filePath == "stdout") fout = ofstream(stdout);
242+
    /// Вывод информации о графе в файл или
243-
		else fout = ofstream(filePath);
243+
    /// на консоль (stdout)
244
    /// </summary>
245-
		if (filePath != "stdout")
245+
    /// <param name="filePath"> путь к файлу или ключевое слово stdout </param>
246-
		{
246+
    void print(string filePath)
247-
			fout << "GRAPH ";
247+
    {
248
        ofstream fout;
249-
			if (IsDirected) fout << "directed ";
249+
250-
			else fout << "undirected ";
250+
        if (filePath == "stdout") fout = ofstream(stdout);
251
        else fout = ofstream(filePath);
252-
			if (IsWeighted) fout << "weighted\n";
252+
253-
			else fout << "unweighted\n";
253+
        if (filePath != "stdout")
254
        {
255-
			fout << "VERTICES: " << _N << "\n";
255+
            fout << "GRAPH ";
256
257-
			for (auto p : graph)
257+
            if (IsDirected) fout << "directed ";
258-
				fout << p.first << "\n";
258+
            else fout << "undirected ";
259
260-
			fout << "EDGES: " << _M << "\n";
260+
            if (IsWeighted) fout << "weighted\n";
261
            else fout << "unweighted\n";
262-
			for (auto p1 : graph)
262+
263-
			{
263+
            fout << "VERTICES: " << _N << "\n";
264-
				Vertice u = p1.first;
264+
265
            for (auto p : graph)
266-
				for (auto p2 : p1.second)
266+
                fout << p.first << "\n";
267-
				{
267+
268-
					Vertice v = p2.first; Edge w = p2.second;
268+
            fout << "EDGES: " << _M << "\n";
269
270-
					if (IsDirected || u < v)
270+
            for (auto p1 : graph)
271-
					{
271+
            {
272-
						fout << u << " " << v << " ";
272+
                Vertice u = p1.first;
273-
						if (IsWeighted) fout << w;
273+
274-
						fout << "\n";
274+
                for (auto p2 : p1.second)
275-
					}
275+
                {
276-
				}
276+
                    Vertice v = p2.first; Edge w = p2.second;
277-
			}
277+
278
                    if (IsDirected || u < v)
279-
			fout.close();
279+
                    {
280-
		}
280+
                        fout << u << " " << v << " ";
281-
		else
281+
                        if (IsWeighted) fout << w;
282-
		{
282+
                        fout << "\n";
283-
			fout << "GRAPH ";
283+
                    }
284
                }
285-
			if (IsDirected) fout << "directed ";
285+
            }
286-
			else fout << "undirected ";
286+
287
            fout.close();
288-
			if (IsWeighted) fout << "weighted\n";
288+
        }
289-
			else fout << "unweighted\n";
289+
        else
290
        {
291-
			fout << "VERTICES: " << _N << "\n";
291+
            fout << "GRAPH ";
292
293-
			for (auto p : graph)
293+
            if (IsDirected) fout << "directed ";
294-
				fout << p.first << "\n";
294+
            else fout << "undirected ";
295
296-
			fout << "EDGES: " << _M << "\n";
296+
            if (IsWeighted) fout << "weighted\n";
297
            else fout << "unweighted\n";
298-
			for (auto p1 : graph)
298+
299-
			{
299+
            fout << "VERTICES: " << _N << "\n";
300-
				Vertice u = p1.first;
300+
301
            for (auto p : graph)
302-
				fout << u << ": ";
302+
                fout << p.first << "\n";
303
304-
				for (auto p2 : p1.second)
304+
            fout << "EDGES: " << _M << "\n";
305-
				{
305+
306-
					Vertice v = p2.first; Edge w = p2.second;
306+
            for (auto p1 : graph)
307
            {
308-
					if (!IsWeighted) fout << v << " ";
308+
                Vertice u = p1.first;
309-
					else fout << "(" << v << ", " << w << ") ";
309+
310-
				}
310+
                fout << u << ": ";
311
312-
				fout << "\n";
312+
                for (auto p2 : p1.second)
313-
			}
313+
                {
314-
		}
314+
                    Vertice v = p2.first; Edge w = p2.second;
315-
	}
315+
316
                    if (!IsWeighted) fout << v << " ";
317
                    else fout << "(" << v << ", " << w << ") ";
318
                }
319
320
                fout << "\n";
321
            }
322
        }
323
    }
324
};
325
326
/// <summary>
327
/// Задание 1a: степени вершин в орграфе
328
/// </summary>
329
/// <typeparam name="Vertice"> тип вершин орграфа </typeparam>
330
/// <typeparam name="Edge"> тип дуг орграфа </typeparam>
331
/// <param name="g"> граф </param>
332
template <class Vertice, class Edge>
333
void VerticesDegrees(Graph<Vertice, Edge> g)
334
{
335-
	/// <summary>
335+
    try
336-
	/// Граф 
336+
    {
337-
	/// </summary>
337+
        if (!g.isDirected()) throw "Задание 1a: работаем с орграфом";
338-
	Graph<Vertice, Edge> g;
338+
        else
339
        {
340-
	/// <summary>
340+
            map <Vertice, int> in_degree, out_degree;
341-
	/// Вывод на консоль списка доступных команд
341+
            map <Vertice, map<Vertice, Edge>> edges = g.edges();
342-
	/// </summary>
342+
343-
	void Hint()
343+
            for (auto p1 : edges)
344-
	{
344+
            {
345-
		cout << "+---------------------------------------+\n";
345+
                Vertice u = p1.first;
346-
		cout << "|             СПИСОК КОМАНД             |\n";
346+
347-
		cout << "+---------------------------------------+\n";
347+
                for (auto p2 : p1.second)
348-
		cout << "|  1. CREATE GRAPH direction weighting  |\n";
348+
                {
349-
		cout << "|  2. CREATE GRAPH filePath             |\n";
349+
                    Vertice v = p2.first;
350-
		cout << "|  3. ADD VERTICE v                     |\n";
350+
351-
		cout << "|  4. REMOVE VERTICE v                  |\n";
351+
                    in_degree[u]++;
352-
		cout << "|  5. ADD EDGE u v [w]                  |\n";
352+
                    out_degree[v]++;
353-
		cout << "|  6. REMOVE EDGE u w                   |\n";
353+
                }
354-
		cout << "|  7. CLEAR GRAPH                       |\n";
354+
            }
355-
		cout << "|  8. PRINT GRAPH filePath              |\n";
355+
356-
		cout << "|  9. GET HINT                          |\n";
356+
            cout << "+---------------+-----------+------------+--------+\n";
357-
		cout << "|  10. EXIT                             |\n";
357+
            cout << "| Вершина       | in_degree | out_degree | degree |\n";
358-
		cout << "+---------------------------------------+\n";
358+
            cout << "+---------------+-----------+------------+--------+\n";
359-
	}
359+
360
            for (auto p : edges)
361
            {
362
                Vertice u = p.first;
363-
	/// <summary>
363+
364-
	/// Конструктор по умолчанию
364+
                int u_in = in_degree[u];
365-
	/// </summary>
365+
                int u_out = out_degree[u];
366-
	ConsoleInterface() {};
366+
367
                cout << left << "| " << setw(14) << u << "| " << setw(10) << u_in << "| " << setw(11) << u_out << "| " << setw(7) << u_in + u_out << "|\n";
368-
	/// <summary>
368+
            }
369-
	/// Запуск интерфейса
369+
370-
	/// </summary>
370+
            cout << "+---------------+-----------+------------+--------+\n";
371-
	void Start()
371+
        }
372-
	{
372+
    }
373-
		Hint();
373+
    catch (const char* msg)
374
    {
375-
		while (true)
375+
        cout << msg << "\n";
376-
		{
376+
    }
377-
			cout << ">> ";
377+
}
378
379-
			string w1; cin >> w1;
379+
380
/// Задание 1а: поиск вершины, соединенной с u и v
381-
			if (w1 == "CREATE")
381+
382-
			{
382+
/// <typeparam name="Vertice"> тип вершин орграфа </typeparam>
383-
				string w2, w3; cin >> w2 >> w3;
383+
/// <typeparam name="Edge"> тип дуг орграфа </typeparam>
384
/// <param name="g"> граф </param>
385-
				if (w3 == "directed" || w3 == "undirected")
385+
/// <param name="u"> первая вершина </param>
386-
				{
386+
/// <param name="v"> вторая вершина </param>
387-
					string w4; cin >> w4;
387+
template <class Vertice, class Edge>
388-
					g = Graph<Vertice, Edge>(w3, w4);
388+
void FindVertice(Graph<Vertice, Edge> g, Vertice u, Vertice v, bool allow_loop)
389-
				}
389+
390-
				else g = Graph<Vertice, Edge>(w3);
390+
    map<Vertice, map<Vertice, Edge>> edges = g.edges();
391-
			}
391+
392-
			else if (w1 == "ADD")
392+
    try
393-
			{
393+
    {
394-
				string w2; cin >> w2;
394+
        if (!g.isDirected()) throw "Задание 1a: работаем с орграфом";
395
        else if (u == v) throw "Задание 1а: вершины u и v должны быть различны";
396-
				if (w2 == "VERTICE")
396+
        else if (edges.find(u) == edges.end() || edges.find(v) == edges.end()) throw "Задание 1а: в графе отсутствует(ют) заданная(ые) вершина(ы)";
397-
				{
397+
        else
398-
					Vertice w3; cin >> w3;
398+
        {
399-
					g.addVertice(w3);
399+
            bool allow_loops = allow_loop;
400-
				}
400+
            vector <Vertice> ans;
401-
				else
401+
402-
				{
402+
            for (auto p : edges[u])
403-
					Vertice w3, w4; Edge w5; cin >> w3 >> w4;
403+
            {
404
                Vertice x = p.first;
405-
					if (!g.isWeighted()) w5 = 1;
405+
                if ((allow_loops || (x != u && x != v)) && edges[v].find(x) != edges[v].end()) ans.push_back(x);
406-
					else cin >> w5;
406+
            }
407
408-
					g.addEdge(w3, w4, w5);
408+
            if (ans.size())
409-
				}
409+
            {
410-
			}
410+
                cout << "Существуют: ";
411-
			else if (w1 == "REMOVE")
411+
412-
			{
412+
                for (int i = 0; i < ans.size(); ++i)
413-
				string w2; cin >> w2;
413+
                    cout << ans[i] << " ";
414
            }
415-
				if (w2 == "VERTICE")
415+
            else cout << "НЕ существуют";
416-
				{
416+
417-
					Vertice w3; cin >> w3;
417+
            cout << "\n";
418-
					g.removeVertice(w3);
418+
        }
419-
				}
419+
    }
420-
				else
420+
    catch (const char* msg)
421-
				{
421+
    {
422-
					Vertice w3, w4; cin >> w3 >> w4;
422+
        cout << msg << "\n";
423-
					g.removeEdge(w3, w4);
423+
    }
424-
				}
424+
}
425-
			}
425+
426-
			else if (w1 == "CLEAR")
426+
427-
			{
427+
/// Задание 1b: удаление ребер в графе с одинаковыми степенями
428-
				string w2; cin >> w2;
428+
429-
				g.clear();
429+
430-
			}
430+
/// <typeparam name="Edge"> тип вершин орграфа </typeparam>
431-
			else if (w1 == "PRINT")
431+
/// <param name="g"> граф </param>
432-
			{
432+
template <class Vertice, class Edge>
433-
				string w2, w3; cin >> w2 >> w3;
433+
void RemoveEdges(Graph<Vertice, Edge> g, string filePath)
434-
				g.print(w3);
434+
435-
			}
435+
    try
436-
			else if (w1 == "GET")
436+
    {
437-
			{
437+
        if (g.isDirected()) throw "Задание 1b: работаем с графом";
438-
				string w2; cin >> w2;
438+
        else
439-
				Hint();
439+
        {
440-
			}
440+
            map<Vertice, int> degree;
441-
			else if (w1 == "EXIT")
441+
            map <Vertice, map<Vertice, Edge>> edges = g.edges();
442-
			{
442+
443-
				break;
443+
            for (auto p1 : edges)
444-
			}
444+
                degree[p1.first] = p1.second.size();
445-
		}
445+
446-
	}
446+
            for (auto p1 : edges)
447
            {
448
                Vertice u = p1.first;
449
450
                for (auto p2 : p1.second)
451
                {
452
                    Vertice v = p2.first;
453
                    if (degree[u] == degree[v] && u < v)
454
                        g.removeEdge(u, v);
455
                }
456
            }
457
458
            g.print(filePath);
459
        }
460
    }
461
    catch (const char* msg)
462
    {
463
        cout << msg << "\n";
464
    }
465
}
466
467
//////////////////////////////////////////////
468
//            ConsoleInterface.h            //
469
//////////////////////////////////////////////
470
471
#pragma once
472
#include "Graph.h"
473
#include <vector>
474
#include <string>
475
476
/// <summary>
477
/// Консольный интерфейс, работающий с одним графом 
478
/// </summary>
479
/// <typeparam name="Vertice"> тип вершин графа </typeparam>
480
/// <typeparam name="Edge"> тип ребер графа </typeparam>
481
template <class Vertice, class Edge = int>
482
class ConsoleInterface
483
{
484
    /// <summary>
485
    /// Граф 
486
    /// </summary>
487
    Graph<Vertice, Edge> g;
488
489
    /// <summary>
490
    /// Вывод на консоль списка доступных команд
491
    /// </summary>
492
    void Hint()
493
    {
494
        cout << "+---------------------------------------+\n";
495
        cout << "|             СПИСОК КОМАНД             |\n";
496
        cout << "+---------------------------------------+\n";
497
        cout << "|  1. CREATE GRAPH direction weighting  |\n";
498
        cout << "|  2. CREATE GRAPH filePath             |\n";
499
        cout << "|  3. ADD VERTICE v                     |\n";
500
        cout << "|  4. REMOVE VERTICE v                  |\n";
501
        cout << "|  5. ADD EDGE u v [w]                  |\n";
502
        cout << "|  6. REMOVE EDGE u w                   |\n";
503
        cout << "|  7. CLEAR GRAPH                       |\n";
504
        cout << "|  8. PRINT GRAPH filePath              |\n";
505
        cout << "|  9. TASK 1                            |\n";
506
        cout << "|  10. TASK 2 u v allow_loop            |\n";
507
        cout << "|  11. TASK 3 filePath                  |\n";
508
        cout << "|  12. GET HINT                         |\n";
509
        cout << "|  13. EXIT                             |\n";
510
        cout << "+---------------------------------------+\n";
511
    }
512
513
public:
514
515
    /// <summary>
516
    /// Конструктор по умолчанию
517
    /// </summary>
518
    ConsoleInterface() {};
519
520
    /// <summary>
521
    /// Запуск интерфейса
522
    /// </summary>
523
    void Start()
524
    {
525
        Hint();
526
527
        while (true)
528
        {
529
            cout << ">> ";
530
531
            string w1; cin >> w1;
532
533
            if (w1 == "CREATE")
534
            {
535
                string w2, w3; cin >> w2 >> w3;
536
537
                if (w3 == "directed" || w3 == "undirected")
538
                {
539
                    string w4; cin >> w4;
540
                    g = Graph<Vertice, Edge>(w3, w4);
541
                }
542
                else g = Graph<Vertice, Edge>(w3);
543
            }
544
            else if (w1 == "ADD")
545
            {
546
                string w2; cin >> w2;
547
548
                if (w2 == "VERTICE")
549
                {
550
                    Vertice w3; cin >> w3;
551
                    g.addVertice(w3);
552
                }
553
                else
554
                {
555
                    Vertice w3, w4; Edge w5; cin >> w3 >> w4;
556
557
                    if (!g.isWeighted()) w5 = 1;
558
                    else cin >> w5;
559
560
                    g.addEdge(w3, w4, w5);
561
                }
562
            }
563
            else if (w1 == "REMOVE")
564
            {
565
                string w2; cin >> w2;
566
567
                if (w2 == "VERTICE")
568
                {
569
                    Vertice w3; cin >> w3;
570
                    g.removeVertice(w3);
571
                }
572
                else
573
                {
574
                    Vertice w3, w4; cin >> w3 >> w4;
575
                    g.removeEdge(w3, w4);
576
                }
577
            }
578
            else if (w1 == "CLEAR")
579
            {
580
                string w2; cin >> w2;
581
                g.clear();
582
            }
583
            else if (w1 == "PRINT")
584
            {
585
                string w2, w3; cin >> w2 >> w3;
586
                g.print(w3);
587
            }
588
            else if (w1 == "TASK")
589
            {
590
                int w2; cin >> w2;
591
592
                if (w2 == 1) VerticesDegrees(g);
593
                else if (w2 == 2)
594
                {
595
                    Vertice u, v; bool b; cin >> u >> v >> b;
596
                    FindVertice(g, u, v, b);
597
                }
598
                else if (w2 == 3)
599
                {
600
                    string w3; cin >> w3; RemoveEdges(g, w3);
601
                }
602
            }
603
            else if (w1 == "GET")
604
            {
605
                string w2; cin >> w2;
606
                Hint();
607
            }
608
            else if (w1 == "EXIT")
609
            {
610
                break;
611
            }
612
        }
613
    }
614
};
615
616
/////////////////////////////////////
617
//            Graph.cpp            //
618
/////////////////////////////////////
619
620
#include "ConsoleInterface.h"
621
#include <Windows.h>
622
623
int main()
624
{
625
	SetConsoleCP(1251);
626
	SetConsoleOutputCP(1251);
627
628
	ConsoleInterface<string, string> consoleInterface;
629
	consoleInterface.Start();
630
631
	return 0;
632
}