[Create graph, breadth and depth traversal, shortest path (Dijkstra), (Prim) and (Kruskal), shortest path (Floyd) algorithm]



#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include<string>
#include <set>
#include <list>
#include <queue>
#include <vector>
#include <map>
#include <iterator>
#include <algorithm>
#include <iostream>




#define MaxVerNum 100 //The maximum number of vertices
#define VexType char //vertex data type
#define EdgeType int //Edge data type, the adjacency matrix is symmetric for an undirected graph, and if it has a value, it means the weight value, and if it is not, 1 is connected to 0 but not connected
#define INF 0x3f3f3f3f//as max

using namespace std;

const int MAXV = 110;
const int MAXE = 10010;
// edge set definition part
struct edge
{
int u, v; //The two endpoint numbers of the edge
int cost; //edge weight
}E[MAXE]; //There are at most MAXE edges

bool cmp(edge a, edge b)
{
return a. cost < b. cost;
}
//and lookup part
int father[MAXV]; //and find the array
int findFather(int x) //and query function
{
int a = x;
while (x != father[x])
{
x = father[x];
}
// path compression
while (a != father[a])
{
int z = a;
a = father[a];
father[z] = x;
}
return x;
}

// graph data structure
typedef struct Graph
{
VexType Vex[MaxVerNum];//vertex table
EdgeType Edge[MaxVerNum][MaxVerNum];//edge table
int vexnum, arcnum;//number of vertices, number of edges
}Graph;


// Dijkstra algorithm global variables
bool S[MaxVerNum]; //Vertex set
int D[MaxVerNum]; //The shortest path to each vertex
int Pr[MaxVerNum]; // record the predecessor


//Data structure used by Prim algorithm
typedef struct closedge
{
int adjvex; //The smallest edge is in the set U (the subscript of the vertex whose smallest edge is in the current subtree vertex set)
int lowcost; //weight on the smallest side
};

//Data structure used by Kruskal algorithm


//**********************************************Basic operation function ***********************************************//
//Initialization function Parameter: graph G Function: initialize the vertex table of the graph, adjacency matrix, etc.
void InitGraph(Graph & G)
{
memset(G.Vex, '#', sizeof(G.Vex));//initialize the vertex table
//Initialize edge table
for (int i = 0; i < MaxVerNum; i ++ )
for (int j = 0; j < MaxVerNum; j++ )
{
G.Edge[i][j] = INF;
if (i == j)G.Edge[i][j] = 0;//In the minimum spanning tree, consider an acyclic simple graph, so set it to 0
}

G.arcnum = G.vexnum = 0; //Initialize the number of vertices and edges
}


// Insert point function Parameters: graph G, vertex v Function: Insert vertex v in graph G, that is, change the vertex table
bool InsertNode(Graph & G, VexType v)
{
if (G.vexnum < MaxVerNum)
{
G.Vex[G.vexnum++] = v;
return true;
}
return false;
}


//Insert edge function Parameters: graph G, v and w at the two ends of a certain edge Function: add an edge between two points v and w in graph G, that is, change the adjacency matrix
bool InsertEdge(Graph & G, VexType v, VexType w, int weight)
{
int p1, p2;//v, w two subscripts
p1 = p2 = -1;//initialization
for (int i = 0; i < G.vexnum; i + + )//find vertex index
{
if (G.Vex[i] == v)p1 = i;
if (G.Vex[i] == w)p2 = i;
}
if (-1 != p1 & amp; & amp; -1 != p2)//Both points can be found in the graph
{
G.Edge[p1][p2] = G.Edge[p2][p1] = weight;//undirected graph adjacency matrix symmetry
G.arcnum++;
return true;
}
return false;
}


//judging whether there is an edge (v,w) function Parameters: graph G, v and w at the two ends of a side Function: judging whether there is an edge (v,w)
bool Adjancent(Graph G, VexType v, VexType w)
{
int p1, p2;//v, w two subscripts
p1 = p2 = -1;//initialization
for (int i = 0; i < G.vexnum; i + + )//find vertex index
{
if (G.Vex[i] == v)p1 = i;
if (G.Vex[i] == w)p2 = i;
}
if (-1 != p1 & amp; & amp; -1 != p2)//Both points can be found in the graph
{
if (G.Edge[p1][p2] == 1)//there is an edge
{
return true;
}
return false;
}
return false;
}


bool visited[MaxVerNum];//Visit mark array, used for mark when traversing
//Breadth traversal function Parameters: graph G, starting node subscript start Function: width traversal
void BFS(Graph G, int start)
{
queue<int> Q;//Auxiliary queue
cout << G.Vex[start];//access node
visited[start] = true;
Q.push(start);//enqueue
while (!Q.empty())//queue is not empty
{
int v = Q.front();//Get the front element of the queue
Q.pop();//Queue
for (int j = 0; j < G.vexnum; j ++ )//adjacent point
{
if (G.Edge[v][j] < INF & amp; & amp; !visited[j])//is an adjacent point and has not been visited
{
cout << "->";
cout << G.Vex[j];//access node
visited[j] = true;
Q.push(j);//enqueue
}
}
}//while
cout << endl;
}


//Deep traversal function (recursive form) parameters: graph G, starting node subscript start Function: depth traversal
void DFS(Graph G, int start)
{
cout << G.Vex[start];//access
visited[start] = true;
for (int j = 0; j < G.vexnum; j++ )
{
if (G.Edge[start][j] < INF & amp; & amp; !visited[j])//is an adjacent point and has not been visited
{
cout << "->";
DFS(G, j);//Recursive depth traversal
}
}
}


//Shortest path - Dijkstra algorithm Parameters: graph G, source point v
void Dijkstra(Graph G, int v)
{
//initialization
int n = G.vexnum;//n is the number of vertices in the graph
for (int i = 0; i < n; i ++ )
{
S[i] = false;
D[i] = G.Edge[v][i];
if (D[i] < INF)Pr[i] = v; //v is connected to i, v is the precursor
else Pr[i] = -1;
}
S[v] = true;
D[v] = 0;
//The initialization is over, find the shortest path, and add the S set
for (int i = 1; i < n; i ++ )
{
int min = INF;
int temp;
for (int w = 0; w < n; w ++ )
if (!S[w] & amp; & amp; D[w] < min) //A certain point temp has not been added to the s set, and it is the current shortest path
{
temp = w;
min = D[w];
}
S[temp] = true;
//Update the shortest path from the source point to other points via temp
for (int w = 0; w < n; w ++ )
if (!S[w] & amp; & amp; D[temp] + G.Edge[temp][w] < D[w])
{
D[w] = D[temp] + G.Edge[temp][w];
Pr[w] = temp;
}
}
}


// output the shortest path
void Path(Graph G, int v)
{
if (Pr[v] == -1)
return;
Path(G, Pr[v]);
cout << G.Vex[Pr[v]] << "->";
}
//********************************************** Function Realization function*****************************************//

// print the vertex table of the graph
void PrintVex(Graph G)
{
for (int i = 0; i < G.vexnum; i ++ )
{
cout << G.Vex[i] << " ";
}
cout << endl;
}


// print the edge matrix of the graph
void PrintEdge(Graph G)
{
for (int i = 0; i < G.vexnum; i ++ )
{
for (int j = 0; j < G.vexnum; j++ )
{
if (G.Edge[i][j] == INF)cout << "∞ ";
else cout << G.Edge[i][j] << " ";
}
cout << endl;
}
}


//Create graph function implementation function Parameter: graph G InsertNode Function: create graph
void CreateGraph(Graph & G)
{
VexType v, w;
int vn, an;//number of vertices, number of edges
cout << "Please enter the number of vertices:" << endl;
cin >> vn;
cout << "Please enter the number of sides:" << endl;
cin >> an;
cout << "Please enter all vertex names:" << endl;
for (int i = 0; i < vn; i ++ )
{
cin >> v;
if (InsertNode(G, v)) continue;//insert point
else {
cout << "Input error!" << endl; break;
}
}
cout << "Please enter all edges (two vertices and weights connected by each input edge):" << endl;
for (int j = 0; j < an; j ++ )
{
int weight;
cin >> v >> w >> weight;
if (InsertEdge(G, v, w, weight)) continue;//insert edge
else {
cout << "Input error!" << endl; break;
}
}
PrintVex(G);
PrintEdge(G);
}


//Breadth traversal function implementation function Parameter: graph G Function: width traversal
void BFSTraverse(Graph G)
{
for (int i = 0; i < MaxVerNum; i ++ )//initialize access tag array
{
visited[i] = false;
}
for (int i = 0; i < G.vexnum; i ++ )//traverse each connected component
{
if (!visited[i])BFS(G, i);
}
}


//Deep traversal function implementation function Parameter: graph G Function: depth traversal
void DFSTraverse(Graph G)
{
for (int i = 0; i < MaxVerNum; i ++ )//initialize access tag array
{
visited[i] = false;
}
for (int i = 0; i < G.vexnum; i ++ )//traverse each connected component
{
if (!visited[i])
{
DFS(G, i); cout << endl;
}
}
}


//Call the shortest path-Dijkstra algorithm Parameters: graph G, source point v
void Shortest_Dijkstra(Graph & G)
{
char vname;
int v = -1;
cout << "Please enter the source name:" << endl;
cin >> vname;
for (int i = 0; i < G.vexnum; i ++ )
if (G.Vex[i] == vname)v = i;
if (v == -1)
{
cout << "No input point found!" << endl;
return;
}
Dijkstra(G, v);
cout << "target point" << "\t" << "shortest path value" << "\t" << "shortest path" << endl;
for (int i = 0; i < G.vexnum; i ++ )
{
if (i != v)
{
cout << " " << G.Vex[i] << "\t" << " " << D[i] << "\t";
Path(G, i);
cout << G.Vex[i] << endl;
}
}
}


//Minimum spanning tree-Prim algorithm Parameters: graph G
void Prim(Graph G)
{
int v = 0;//initial node
closedge C[MaxVerNum];
int mincost = 0; //Record the sum of the weights of each side of the minimum spanning tree
//initialization
for (int i = 0; i < G.vexnum; i ++ )
{
C[i].adjvex = v;
C[i].lowcost = G.Edge[v][i];
}
cout << "All edges of the minimum spanning tree:" << endl;
//Initialization is complete, start G.vexnum-1 cycle
for (int i = 1; i < G.vexnum; i ++ )
{
int k;
int min = INF;
// Find the point with the smallest weight to the set U. The representative with a weight of 0 is in the set U
for (int j = 0; j < G.vexnum; j++ )
{
if (C[j].lowcost != 0 & amp; & amp; C[j].lowcost < min)
{
min = C[j].lowcost;
k = j;
}
}
//Output the selected edge and accumulate the weight
cout << "(" << G.Vex[k] << "," << G.Vex[C[k].adjvex] << ") ";
mincost + = C[k].lowcost;
//Update the smallest edge
for (int j = 0; j < G.vexnum; j++ )
{
if (C[j].lowcost != 0 & amp; & amp; G.Edge[k][j] < C[j].lowcost)
{
C[j].adjvex = k;
C[j].lowcost = G.Edge[k][j];
}
}

}
cout << "Sum of minimum spanning tree weights:" << mincost << endl;
}


//kruskal part, return the sum of the edge weights of the minimum spanning tree, the parameter n is the number of vertices, m is the number of edges of the graph
int kruskal(int n, int m)
{
//ans is the sum of the requested edge weights, and Num_Edge is the number of edges in the current spanning tree
int ans = 0, Num_Edge = 0;
for (int i = 0; i < n; i ++ ) //vertex range is [0,n-1]
{
father[i] = i; //and check set initialization
}
sort(E, E + m, cmp); //All edges are sorted by edge weight from small to large
for (int i = 0; i < m; i ++ ) //enumerate all edges
{
int faU = findFather(E[i].u); //Query the root node of the set where the two endpoints of the test edge are located
int faV = findFather(E[i].v);
if (faU != faV) //if not in a collection
{
father[faU] = faV; //Merge sets (that is, add the test edge to the minimum spanning tree)
ans + = E[i].cost; //The sum of edge weights increases the edge weight of the test edge
Num_Edge ++ ; //Increase the number of edges of the current spanning tree by 1
if (Num_Edge == n - 1)
break; //End the algorithm when the number of edges is equal to the number of vertices minus 1
}
}
if (Num_Edge != n - 1)
return -1; //Return -1 when unable to connect
else
return ans; //Return the sum of edge weights of the minimum spanning tree
}


//Minimum Spanning Tree-Kruskal Algorithm (Kruskal) Parameters: Figure
void Kruskal01() {
cout << "Welcome to Kruskal Algorithm" << endl;
int n, m;
cout << "Please enter the number of vertices and edges" << endl;
scanf_s("%d%d", & amp;n, & amp;m); //number of vertices, number of edges
for (int i = 0; i < m; i ++ )
{
cout << "Please enter the weight of the first" << i + 1 << "edge" << endl;
scanf_s("%d%d%d", & amp;E[i].u, & amp;E[i].v, & amp;E[i].cost); //Two endpoint numbers, sides right
}
int ans = kruskal(n, m); //kruskal algorithm entry
printf_s("The shortest path is: %d\
", ans);
}


//Shortest path problem - Floyd's algorithm
void Floyd() {
cout << "Welcome to Floyd's Algorithm!" << endl;
int a[21][21], m, n, i, j, w;
for (int i = 1; i <= 20; i ++ ) {
for (int j = 1; j <= 20; j ++ ) {
if (i == j) { a[i][j] = 0; }
else a[i][j] = INF;
}
}
cin >> n >> m;
cout << "The number of vertices and edges has been entered" << endl;
for (int k = 1; k <= m; k ++ ) {
cin >> i >> j >> w;
a[i][j] = w;
a[j][i] = w;
}
for (int p = 1; p <= n; p ++ ) {
for (int i = 1; i <= n; i ++ ) {
if (a[i][p] == INF) continue;
for (int j = 1; j <= n; j ++ ) {
if (i == j)continue;
a[i][j] = min(a[i][j], a[i][p] + a[p][j]);
}
}
}
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= n; j ++ ) {
cout << a[i][j] << " ";
}
cout << endl;
}
}






//menu
void menu()
{
cout << "************1. Create graph 2. Breadth traversal *******************" << endl;
cout << "************3. Depth Traversal 4. Shortest Path (Dijkstra)****************" << endl;
cout << "************5. Minimum spanning tree (Prim) 6. Minimum spanning tree (Kruskal) *****************" < < endl;
cout << "************7. Shortest path (Floyd) 8. Exit program *****************" << endl;
// cout << "9. Exit the program *****************" << endl;
}


//main function
int main()
{
int choice = 0;
Graph G;
InitGraph(G);
while (1)
{
menu();
printf("Please enter the menu number:\
");
scanf_s("%d", &choice);
if (8 == choice) break;
switch (choice)
{
case 1:CreateGraph(G); break;
case 2: BF Traverse(G); break;
case 3:DFSTraverse(G); break;
//case 4:Shortest_Dijkstra(G); break;
case 4: Dijkstra(G,2); break;
case 5: Prim(G); break;
case 6: Kruskal01(); break;
case 7: Floyd(); break;
case 8: break;
default:printf("Input error!!!\
"); break;
}
}
return 0;
}