Fast Achievement of Algorithmic Series in 15 Days — Fifteenth Days Map [Part Two] (General Outcome)

Time:2019-8-13

Today is the big ending. Let’s talk about the last thing of “graph”, “minimum spanning tree” and “shortest path”.

One: Minimum Spanning Tree

1. Concept

First of all, look at the following figure, I don’t know what you can sum up.

For a connected graph G, if all its vertices and some edges constitute a subgraph G1, when G1 satisfies:

It connects all vertices in the graph. (2) There is no loop at the vertex. G 1 is the “spanning tree” of G.

In fact, a sentence is summarized as follows: Spanning tree is a subgraph that connects all vertices of the original graph with the smallest edge. No, the following connected graph can get the following two spanning trees.

(2) For a weighted connected graph, when the generated tree is different, the sum of weights on each edge is different. If the weight of a spanning tree is the smallest, it is the “smallest spanning tree”.

     

2. Scene

In practical application, “minimum spanning tree” is quite valuable. There is a sentence in the textbook. If a transportation system is represented by a graph, each vertex represents a city.

The edge represents the distance between two cities. When there are n cities, there may be n (n-1)/2 edges. So how to choose (n-1) edges to minimize the total distance between cities?

The abstract model of “minimal spanning tree” is the problem of seeking “minimal spanning tree”.

 

3. Prim algorithm

Of course, how to find the “minimum spanning tree” problem has been summarized by our predecessors. We just need to follow the gourd to draw a ladle.

First step: We set up the set “V, U” and inject all vertices in the graph into the set of V. The set of U is initially empty.

Step 2: We put V1 into the U set and mark the V1 vertex as accessed. At this time: U (V1).

Step 3: We look for the adjacent points (V2, V3, V5) of V1, and find the minimum weight among the weights (V1, V2). At this time, we put V2 into the U set and mark V2 as accessed.

This is U (V1, V2).

Step 4: We find the adjacent edges of V1 and V2 in the U set. After a convulsion, we find that the weight of (V1, V5) is the smallest. At this time, we add V5 to the U set and mark it as accessed.

The set elements of U are (V1, V2, V5).

Step 5: At this time, we use (V1, V2, V5) as the benchmark to find the adjacent edge of the minimum weight around, and find that (V5, V4) has the smallest weight. At this time, we add V4 to the U set and mark it.

For access, the set elements of U are (V1, V2, V5, V4).

Step 6: As in Step 5, the minimum weight (V1, V3) is found. V3 is added to the U set and marked as accessed. The final U element is (V1, V2, V5, V4, V3).

Finally, it was found that all the vertices were accessed, and the minimum spanning tree was born.

Copy codeThe code is as follows:
# Minimum Spanning Tree Acquisition by Region Prim Algorithms
        /// <summary>
/// Minimum Spanning Tree Acquisition by Prim Algorithms
/// </summary>
/// <param name=”graph”></param>
        public void Prim(MatrixGraph graph, out int sum)
        {
// Visited logo
            int used = 0;

// Non-adjacent vertex markers
            int noadj = -1;

// Define a variable that outputs the total weight
            sum = 0;

// Temporary array to hold the weights of adjacent points
            int[] weight = new int[graph.vertexNum];

// Temporary array to hold vertex information
            int[] tempvertex = new int[graph.vertexNum];

// Take out the first row of adjacency matrix, that is, take out the first vertex and save the weight and edge information in temporary data.
            for (int i = 1; i < graph.vertexNum; i++)
            {
// Weights stored between adjacent points
                weight[i] = graph.edges[0, i];

// Equal to 0 means that V1 has no edge with the adjacent point.
                if (weight[i] == short.MaxValue)
                    tempvertex[i] = noadj;
                else
                    tempvertex[i] = int.Parse(graph.vertex[0]);
            }

// Remove the V1 node from the set V, just set the node to be accessed and weight to the set 0
            var index = tempvertex[0] = used;
            var min = weight[0] = short.MaxValue;

// Finding the Node with the Minimum Weight in the Adjacent Point of V
            for (int i = 1; i < graph.vertexNum; i++)
            {
                index = i;
                min = short.MaxValue;

                for (int j = 1; j < graph.vertexNum; j++)
                {
// Used to find the least weight unaccessible point in the current node’s adjacent points
                    if (weight[j] < min && tempvertex[j] != 0)
                    {
                        min = weight[j];
                        index = j;
                    }
                }
// cumulative weighted value
                sum += min;

                Console.Write(“({0},{1})  “, tempvertex[index], graph.vertex[index]);

// Identify the minimum node obtained as accessed
                weight[index] = short.MaxValue;
                tempvertex[index] = 0;

// Starting from the latest node, the weights of this node are evaluated.
                for (int j = 0; j < graph.vertexNum; j++)
                {
// Re-select the smallest edge from the current node
                    if (graph.edges[index, j] < weight[j] && tempvertex[j] != used)
                    {
                        weight[j] = graph.edges[index, j];

// The purpose here is to cover the longer edges in the adjacent points of a node at a shorter edge cover point.
                        tempvertex[j] = int.Parse(graph.vertex[index]);
                    }
                }
            }
        }
        #endregion

Second: Shortest Path

1. Concept

In fact, finding the shortest path problem is also very useful. Mapping to the traffic system diagram is to find the shortest path problem between two cities. Looking at this picture, we can easily see, for example.

The shortest path from V1 to each vertex in the graph.

(1) V1-> V2) direct, weighting 2.

(2) V1-> V3 direct right is 3.

(3) V1->V5->V4 transit weight is 3+2=5.

(4) V1-> V5 direct right is 3.

 

2. Dijkstra algorithm

Our learning needs to stand on the shoulders of giants, so for the very complex problems in reality, we certainly can not see with the naked eye, but based on certain algorithms derived.

Dijkstra’s thought follows the principle of “one step, one step”.

Step 1: We need a set U, and then put V1 into the U set. Now that we have taken a step, we need to take a look at the adjacent points of V1 (V2, V3, V5).

It is found that the weight of (V1, V2) is the smallest. At this time, we put V2 into the U set, indicating that we have found the shortest path between V1 and V2.

Step 2: Then make V2 as the middle point and continue to search for the nearest neighbor with the smallest weight. It is found that only V4 can be connected. At this time, the weight of V4 is modified to be (V1, V2) + (V2, V4) = 6.

At this point, we have to take a step to find that the minimum weight of V1 to (V3, V4, V5) is (V1, V5). At this time, we put V5 into the U set, indicating that we have found it.

The shortest path from V1 to V5.

Step 3: Then we use V5 as the middle point and continue to search for the nearest neighbor with the smallest weight. We find that V3 and V4 can be connected. When we are trying to repair the weight of V3, we find the weight of (V1, V3).

Less than (V1 – > V5 – > V3), at this time we do not modify, V3 into the U set, and finally we find the shortest path from V1 to V3.

Step 4: Because V5 has not finished yet, we continue to use V5 as the intermediate point. At this time, we can only connect (V5, V4). When we want to modify the weights, we find that the original V4 weights are (V1, V2) + (V2, V4), and

Now the weight is 5, less than the previous 6, then change the original weight to 5, put V4 into the set, and finally we find the shortest path from V1 to V4.

Copy codeThe code is as follows:
# region Dijkstra finds the shortest path
        /// <summary>
/// Dijkstra Finds the Shortest Path
/// </summary>
/// <param name=”g”></param>
        public void Dijkstra(MatrixGraph g)
        {
            int[] weight = new int[g.vertexNum];

            int[] path = new int[g.vertexNum];

            int[] tempvertex = new int[g.vertexNum];

Console. WriteLine (” n Please enter the number of the source point:”);

// Let the user enter the starting point to traverse
            int vertex = int.Parse(Console.ReadLine()) – 1;

            for (int i = 0; i < g.vertexNum; i++)
            {
// Initial weighting
                weight[i] = g.edges[vertex, i];

                if (weight[i] < short.MaxValue && weight[i] > 0)
                    path[i] = vertex;

                tempvertex[i] = 0;
            }

            tempvertex[vertex] = 1;
            weight[vertex] = 0;

            for (int i = 0; i < g.vertexNum; i++)
            {
                int min = short.MaxValue;

                int index = vertex;

                for (int j = 0; j < g.vertexNum; j++)
                {
// Find the smallest among the weights of vertices
                    if (tempvertex[j] == 0 && weight[j] < min)
                    {
                        min = weight[j];
                        index = j;
                    }
                }

                tempvertex[index] = 1;

// Take the current index as the middle point to find the minimum weight
                for (int j = 0; j < g.vertexNum; j++)
                {
                    if (tempvertex[j] == 0 && weight[index] + g.edges[index, j] < weight[j])
                    {
                        weight[j] = weight[index] + g.edges[index, j];
                        path[j] = index;
                    }
                }
            }

Console. WriteLine (” n vertex {0} to each vertex the shortest path is: (endpoint < source point)” + g. vertex [vertex]);

// Final output
            for (int i = 0; i < g.vertexNum; i++)
            {
                if (tempvertex[i] == 1)
                {
                    var index = i;

                    while (index != vertex)
                    {
                        var j = index;
                        Console.Write(“{0} < “, g.vertex[index]);
                        index = path[index];
                    }
                    Console.WriteLine(“{0}\n”, g.vertex[index]);
                }
                else
                {
Console.WriteLine (“{0} <-{1}: no pathn”, g.vertex [i], g.vertex [vertex]);
                }
            }
        }
        #endregion

Finally, let’s look at the overall running code

Copy codeThe code is as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MatrixGraph
{
    public class Program
    {
        static void Main(string[] args)
        {
            MatrixGraphManager manager = new MatrixGraphManager();

// Create a diagram
            MatrixGraph graph = manager.CreateMatrixGraph();

            manager.OutMatrix(graph);

            int sum = 0;

            manager.Prim(graph, out sum);

Console. WriteLine (” n Minimum Spanning Tree Weight:”+sum”;

            manager.Dijkstra(graph);

// Console. Write (“breadth recursion:\ t”);

//manager.BFSTraverse(graph);

// Console. Write (” n depth recursion: t”);

//manager.DFSTraverse(graph);

            Console.ReadLine();

        }
    }

# Structural Diagram of Region Adjacency Matrix
    /// <summary>
/// Structure Diagram of Adjacency Matrix
/// </summary>
    public class MatrixGraph
    {
// Save vertex information
        public string[] vertex;

// Save edge information
        public int[,] edges;

// Traversal Signs of Deep Search and Wide Search
        public bool[] isTrav;

// Number of vertices
        public int vertexNum;

// Edge Quantity
        public int edgeNum;

// Graph type
        public int graphType;

        /// <summary>
/// Initialization of storage capacity
/// </summary>
/// <param name=”vertexNum”></param>
/// <param name=”edgeNum”></param>
/// <param name=”graphType”></param>
        public MatrixGraph(int vertexNum, int edgeNum, int graphType)
        {
            this.vertexNum = vertexNum;
            this.edgeNum = edgeNum;
            this.graphType = graphType;

            vertex = new string[vertexNum];
            edges = new int[vertexNum, vertexNum];
            isTrav = new bool[vertexNum];
        }

    }
    #endregion

    /// <summary>
/// Operational Classes of Graphs
/// </summary>
    public class MatrixGraphManager
    {
# Creation of Region Graph
        /// <summary>
/// Graph Creation
/// </summary>
/// <param name=”g”></param>
        public MatrixGraph CreateMatrixGraph()
        {
Console.WriteLine (“Please enter the number of vertices, edges, and whether they are undirected graphs (0,1) separated by commas. “”;

            var initData = Console.ReadLine().Split(‘,’).Select(i => int.Parse(i)).ToList();

            MatrixGraph graph = new MatrixGraph(initData[0], initData[1], initData[2]);

// We acquiesce that “positive infinity is boundless”
            for (int i = 0; i < graph.vertexNum; i++)
            {
                for (int j = 0; j < graph.vertexNum; j++)
                {
                    graph.edges[i, j] = short.MaxValue;
                }
            }

Console. WriteLine (“Please enter vertex information:”);

            for (int i = 0; i < graph.vertexNum; i++)
            {
Console. Write (” n th”+ (i + 1) + “vertex is:”);

                var single = Console.ReadLine();

// Vertex information is added to the set
                graph.vertex[i] = single;
            }

Console. WriteLine (“\ n Please enter the edges and weights that make up the two vertices separated by commas. \n “”;

            for (int i = 0; i < graph.edgeNum; i++)
            {
Console. Write (“Tier”+ (i + 1) + “Strip Edge: t”);

                initData = Console.ReadLine().Split(‘,’).Select(j => int.Parse(j)).ToList();

                int start = initData[0];
                int end = initData[1];
                int weight = initData[2];

// assigning coordinate positions to a matrix
                graph.edges[start – 1, end – 1] = weight;

// If it is an undirected graph, the data is “two, four” quadrant symmetric.
                if (graph.graphType == 1)
                {
                    graph.edges[end – 1, start – 1] = weight;
                }
            }

            return graph;
        }
        #endregion

# Region Output Matrix Data
        /// <summary>
/// Output Matrix Data
/// </summary>
/// <param name=”graph”></param>
        public void OutMatrix(MatrixGraph graph)
        {
            for (int i = 0; i < graph.vertexNum; i++)
            {
                for (int j = 0; j < graph.vertexNum; j++)
                {
                    if (graph.edges[i, j] == short.MaxValue)
                        Console.Write(“∽\t”);
                    else
                        Console.Write(graph.edges[i, j] + “\t”);
                }
// Line change
                Console.WriteLine();
            }
        }
        #endregion

# Region breadth first
        /// <summary>
/// breadth first
/// </summary>
/// <param name=”graph”></param>
        public void BFSTraverse(MatrixGraph graph)
        {
// Access Markup Default Initialization
            for (int i = 0; i < graph.vertexNum; i++)
            {
                graph.isTrav[i] = false;
            }

// Traverse each vertex
            for (int i = 0; i < graph.vertexNum; i++)
            {
// Width traversal of unvisited vertices
                if (!graph.isTrav[i])
                {
                    BFSM(ref graph, i);
                }
            }
        }

        /// <summary>
/// Specific algorithm of breadth traversal
/// </summary>
/// <param name=”graph”></param>
        public void BFSM(ref MatrixGraph graph, int vertex)
        {
// Here is the queue of the system.
            Queue<int> queue = new Queue<int>();

// Get to the top first
            queue.Enqueue(vertex);

// Mark that the vertex has been accessed
            graph.isTrav[vertex] = true;

// Output vertex
            Console.Write(” ->” + graph.vertex[vertex]);

// Adjacent Points of Width Traversal Vertices
            while (queue.Count != 0)
            {
                var temp = queue.Dequeue();

// abscissa of ergodic matrix
                for (int i = 0; i < graph.vertexNum; i++)
                {
                    if (!graph.isTrav[i] && graph.edges[temp, i] != 0)
                    {
                        graph.isTrav[i] = true;

                        queue.Enqueue(i);

// Output of unaccounted vertices
                        Console.Write(” ->” + graph.vertex[i]);
                    }
                }
            }
        }
        #endregion

# Region depth first
        /// <summary>
/// Depth first
/// </summary>
/// <param name=”graph”></param>
        public void DFSTraverse(MatrixGraph graph)
        {
// Access Markup Default Initialization
            for (int i = 0; i < graph.vertexNum; i++)
            {
                graph.isTrav[i] = false;
            }

// Traverse each vertex
            for (int i = 0; i < graph.vertexNum; i++)
            {
// Width traversal of unvisited vertices
                if (!graph.isTrav[i])
                {
                    DFSM(ref graph, i);
                }
            }
        }

# concrete algorithm of region depth recursion
        /// <summary>
/// Specific algorithm of depth recursion
/// </summary>
/// <param name=”graph”></param>
/// <param name=”vertex”></param>
        public void DFSM(ref MatrixGraph graph, int vertex)
        {
            Console.Write(“->” + graph.vertex[vertex]);

// Marked as accessed
            graph.isTrav[vertex] = true;

// Six points to traverse
            for (int i = 0; i < graph.vertexNum; i++)
            {
                if (graph.isTrav[i] == false && graph.edges[vertex, i] != 0)
                {
// Deep recursion
                    DFSM(ref graph, i);
                }
            }
        }
        #endregion
        #endregion

# Minimum Spanning Tree Acquisition by Region Prim Algorithms
        /// <summary>
/// Minimum Spanning Tree Acquisition by Prim Algorithms
/// </summary>
/// <param name=”graph”></param>
        public void Prim(MatrixGraph graph, out int sum)
        {
// Visited logo
            int used = 0;

// Non-adjacent vertex markers
            int noadj = -1;

// Define a variable that outputs the total weight
            sum = 0;

// Temporary array to hold the weights of adjacent points
            int[] weight = new int[graph.vertexNum];

// Temporary array to hold vertex information
            int[] tempvertex = new int[graph.vertexNum];

// Take out the first row of adjacency matrix, that is, take out the first vertex and save the weight and edge information in temporary data.
            for (int i = 1; i < graph.vertexNum; i++)
            {
// Weights stored between adjacent points
                weight[i] = graph.edges[0, i];

// Equal to 0 means that V1 has no edge with the adjacent point.
                if (weight[i] == short.MaxValue)
                    tempvertex[i] = noadj;
                else
                    tempvertex[i] = int.Parse(graph.vertex[0]);
            }

// Remove the V1 node from the set V, just set the node to be accessed and weight to the set 0
            var index = tempvertex[0] = used;
            var min = weight[0] = short.MaxValue;

// Finding the Node with the Minimum Weight in the Adjacent Point of V
            for (int i = 1; i < graph.vertexNum; i++)
            {
                index = i;
                min = short.MaxValue;

                for (int j = 1; j < graph.vertexNum; j++)
                {
// Used to find the least weight unaccessible point in the current node’s adjacent points
                    if (weight[j] < min && tempvertex[j] != 0)
                    {
                        min = weight[j];
                        index = j;
                    }
                }
// cumulative weighted value
                sum += min;

                Console.Write(“({0},{1})  “, tempvertex[index], graph.vertex[index]);

// Identify the minimum node obtained as accessed
                weight[index] = short.MaxValue;
                tempvertex[index] = 0;

// Starting from the latest node, the weights of this node are evaluated.
                for (int j = 0; j < graph.vertexNum; j++)
                {
// Re-select the smallest edge from the current node
                    if (graph.edges[index, j] < weight[j] && tempvertex[j] != used)
                    {
                        weight[j] = graph.edges[index, j];

// The purpose here is to cover the longer edges in the adjacent points of a node at a shorter edge cover point.
                        tempvertex[j] = int.Parse(graph.vertex[index]);
                    }
                }
            }
        }
        #endregion

# region Dijkstra finds the shortest path
        /// <summary>
/// Dijkstra Finds the Shortest Path
/// </summary>
/// <param name=”g”></param>
        public void Dijkstra(MatrixGraph g)
        {
            int[] weight = new int[g.vertexNum];

            int[] path = new int[g.vertexNum];

            int[] tempvertex = new int[g.vertexNum];

Console. WriteLine (” n Please enter the number of the source point:”);

// Let the user enter the starting point to traverse
            int vertex = int.Parse(Console.ReadLine()) – 1;

            for (int i = 0; i < g.vertexNum; i++)
            {
// Initial weighting
                weight[i] = g.edges[vertex, i];

                if (weight[i] < short.MaxValue && weight[i] > 0)
                    path[i] = vertex;

                tempvertex[i] = 0;
            }

            tempvertex[vertex] = 1;
            weight[vertex] = 0;

            for (int i = 0; i < g.vertexNum; i++)
            {
                int min = short.MaxValue;

                int index = vertex;

                for (int j = 0; j < g.vertexNum; j++)
                {
// Find the smallest among the weights of vertices
                    if (tempvertex[j] == 0 && weight[j] < min)
                    {
                        min = weight[j];
                        index = j;
                    }
                }

                tempvertex[index] = 1;

// Take the current index as the middle point to find the minimum weight
                for (int j = 0; j < g.vertexNum; j++)
                {
                    if (tempvertex[j] == 0 && weight[index] + g.edges[index, j] < weight[j])
                    {
                        weight[j] = weight[index] + g.edges[index, j];
                        path[j] = index;
                    }
                }
            }

Console. WriteLine (” n vertex {0} to each vertex the shortest path is: (endpoint < source point)” + g. vertex [vertex]);

// Final output
            for (int i = 0; i < g.vertexNum; i++)
            {
                if (tempvertex[i] == 1)
                {
                    var index = i;

                    while (index != vertex)
                    {
                        var j = index;
                        Console.Write(“{0} < “, g.vertex[index]);
                        index = path[index];
                    }
                    Console.WriteLine(“{0}\n”, g.vertex[index]);
                }
                else
                {
Console.WriteLine (“{0} <-{1}: no pathn”, g.vertex [i], g.vertex [vertex]);
                }
            }
        }
        #endregion
    }
}

 

Fast-track algorithm series is now all over, and the company’s algorithm training for us ended last Friday. Ha-ha, catch up with the synchronization. Finally, I hope you can attach importance to the algorithm.

Learn the algorithm well, life-long benefits.