Graph theory (i): Dfs,bfs, adjacency list, and search set

Source: Internet
Author: User

This paper summarizes the depth-first search of graphs, the breadth-first search of graphs, the implementation of adjacency linked lists and adjacency matrices, and the implementation of check sets.

0), Pre-knowledge
Basic Vocabulary: The direction graph, the non-direction graph, the weighted direction graph, the weighted graph, the <vi, Vj>: That is, vi--->vj, ARC tail---> Arc Head, the adjacent graph is recorded as (vi, VJ), Vertex has poor set of v+ side of the poor set E.
Two implementations of the graph: 1, adjacency matrix: edge[n][n] indicates that there are N nodes, the contents of the array is the weight value or whether there is an edge (∞ means infinity, weights or 1 means there is an edge, 0 means node to the node itself);
2, adjacency list: For the sparse matrix is more appropriate, for each vertex of the graph to establish a single-linked list, the first single-linked table to save and node vi all adjacent node information (no map) or ARC tail node information (directed graph), and edge information.


1), graph of depth-first search (DFS)
The main idea of the depth-first algorithm is to first take an unused vertex as the starting vertex, walk along the edge of the current vertex to the vertex that has not been visited, and when there are no vertices that have not been visited, go back to the previous vertex and continue the temptation to access the other vertices until all the vertices have been accessed. It is clear that the depth-first traversal is traversed along a branch of the graph until the end, then backtracking, and then the same traversal along the other line.
Example 1: For example, starting from Node 1 DFS, the algorithm idea of the program is: Initialize the connection matrix in the main function, call DFS (1)---> Set the variable cnt, the CNT equals the number of nodes as the critical condition of DFS recursion---> Set flag mark[n], DFS dispatch access when the next node that the edge of the current access node points to is not accessed (the order in which adjacent nodes of the node is accessed in the order of labels from small to large)


/*** first enter n nodes, M-bar, followed by the M-edge of the no-map, followed by the node order of the output DFS traversal ***/#include <iostream> #include <iomanip> #define NMAX 110#define inf 999999999using namespace Std;int N, M, CNT, Edge[nmax][nmax], mark[nmax];//node, edge count, Count value, adjacency matrix, node access mark void Dfs (int cur) {cnt+ +;/***operation***/if (cnt = 1) cout << cur;else cout << setw (3) << cur;/***operation***/if (cnt = = N) ret Urn;else{int i;for (i = 1; I <= n; i++) {if (edge[cur][i] = = 1 && mark[i] = = 0) {Mark[i] = 1;dfs (i);}} return;}} int main () {while (CIN >> n >> m && n! = 0) {//initialize adjacency matrix int i, j;for (i = 1; I <= n; i++) {for (j = 1; J &L t;= N; J + +) {Edge[i][j] = inf;} Edge[i][i] = 0;} int A, b;while (m--) {cin >> a >> b;edge[a][b] = edge[b][a] = 1;} Start with DNF (1) as the starting point for recursive traversal of memset (mark, 0, sizeof (Mark)), cnt = 0;mark[1] = 1;dfs (1); cout << Endl;} return 0;} 
       program Run Result:

Example 2: Below is a map of the city, note is a one-way map, the City 1 to the shortest distance from the city 5
Program ideas: From the city of 1th, can reach the city of 2nd and 5th, if the order of 1 to N first visited the city of 2nd, after the visit of the 2nd city, because the city of 2nd cities can reach the city of 3rd and 5th, we visited City 3rd, and thereafter, 3rd City can reach 1th, 4th city, Since City 1th has been visited, we have visited City 4th, City 4th is also reachable in city 5th, and we have visited City No. 5th last. However, 1->2->3->4->5 is not necessarily the shortest path, we need to remove the access mark of City 5th and return to City 4th, which has been visited by City No. 4th and no other city has access to City No. 3rd. Visit City No. 4th through City 3rd, then see if you can access city 5th, and then return to City 2nd, when the city of 2nd has a direct route 5th city, namely 1->2->5 .... So retrace and go forward until all 1th cities can reach the route of City 5th, whichever is the smallest.


/*** first input n nodes, M edge, followed by input to the M-bar edge of the graph, the first two elements of the edge represents the starting node, the third value table weight, the output of city 1th to n the shortest distance ***//*** algorithm is to access all deep traversal paths, need to be in the depth of the return of the access flag 0** */#include <iostream> #include <iomanip> #define NMAX 110#define inf 999999999using namespace Std;int N, m, min Path, Edge[nmax][nmax], mark[nmax];//node, edge number, minimum path, adjacency matrix, node access token void Dfs (int cur, int dst) {/***operation***//*** operation***/if (Minpath < DST) return;//current traversed path is greater than before shortest path, no need to go further if (cur = = N) {//Critical condition if (Minpath > DST) minpath = DST; return;}  Else{int i;for (i = 1; I <= n; i++) {if (Edge[cur][i]! = INF && edge[cur][i]! = 0 && Mark[i] = = 0) {Mark[i] = 1;dfs (i, dst+edge[cur][i]); Mark[i] = 0;}} return;}} int main () {while (CIN >> n >> m && n! = 0) {//initialize adjacency matrix int i, j;for (i = 1; I <= n; i++) {for (j = 1; J &L t;= N; J + +) {Edge[i][j] = inf;} Edge[i][i] = 0;} int A, b;while (m--) {cin >> a >> b;cin >> edge[a][b];} Start with DNF (1) as the starting point for recursive traversal of memset (mark, 0, sizeof), Minpath = inf;mark[1] = 1;dfs (1, 0), cout << minpath << Endl;}return 0;} 

The results of the program run as follows:



2), Chart Breadth First search (BFS)
The main idea of breadth-first traversal is to first access all of its adjacent vertices with an unreachable vertex, and then to each adjacent vertex, and then to its adjacent, inaccessible vertices until all the vertices have been accessed and the traversal ends.

Example 1: According to 1) Example 1 of the non-direction graph, the output of its breadth-first search order.
The main idea of the program: Node 1 team---> while the queue is not empty according to the loop---> Outbound and the adjacent nodes are queued, in addition to set the count of CNT, each time out of the team plus 1.

/*** first Enter n nodes, m edges, then the M-edge of the non-direction graph, and the two element of the edge represents the starting node ***/#include <iostream> #include <queue> #include <iomanip  >using namespace std; #define NMAX 110#define inf 999999999queue<int> que;int N, M, Mark[nmax], Edge[nmax][nmax],  Cnt;int Main () {while (CIN >> n >> m && n! = 0) {int i, j;//initialize adjacency list for (i = 1; I <= n; i++) {for (j = 1; J <= N; J + +) {Edge[i][j] = inf;} Edge[i][i] = 0;} int A, b;while (m--) {cin >> a >> b;edge[a][b] = edge[b][a] = 1;} while (!que.empty ()) Que.pop (); memset (mark, 0, sizeof);//start Breadth First traverse int head;cnt = 0;mark[1] = 1;que.push (1); while (! Que.empty ()) {head = Que.front (); Que.pop ()/***operation***/cnt++;if (cnt = = 1) cout << head;elsecout << SETW (3) << head;/***operation***/for (i = 1; I <= n; i++) {if (edge[head][i] = = 1 && mark[i] = = 0) {Mark[i] = 1;q Ue.push (i);}}} cout << endl;if (cnt! = N) cout << "The original image is not connected.\n";} return 0;}
        The results of the program run as follows:



Example 2: If you need to fly from city 1th to City 5th, ask for the minimum number of connections


/*** first input n nodes, M-Edge, departure city, end city, then input the M-edge of the graph, the edge of the two element represents the starting node ***//*** need to construct node structure node, the node number and the number of traversal layer, each for the number of layers on the previous layer on the basis of adding 1***/# Include <iostream> #include <queue>using namespace std, #define NMAX 110#define inf 999999999struct node{int Node;int CNT;};  Queue<node> Que;int m, N, Edge[nmax][nmax], Mark[nmax], Startnum, Endnum;int main () {while (CIN >> n >> m >> startnum >> endnum && n! = 0) {bool tag = false;//Initialize adjacency matrix int i, j;for (i = 1; I <= n; i++) {for (J = 1; J <= N; J + +) {Edge[i][j] = inf;} Edge[i][i] = 0;} while (m--) {cin >> i >> j;edge[i][j] = edge[j][i] = 1;} Start breadth-first traversal of memset (mark, 0, sizeof), while (!que.empty ()) Que.pop (); Node Tmp;tmp.node = startnum;tmp.cnt = 0;que.push (TMP); Mark[tmp.node] = 1;while (!que.empty ()) {node head = Que.front (); Que.pop ();  Node temp;for (i = 1; I <= n; i++) {if (edge[head.node][i] = = 1 && mark[i] = = 0) {Temp.node = i;temp.cnt = head.cnt + 1;que.push (temp);//note written inside the IF statement mark[temp.node] = 1;if (Temp.node = = Endnum) {tag = true;cout << temp.cnt << Endl;break;}}} if (tag) break;}} return 0;}
    The results of the program run as follows:




3), adjacency linked list and adjacency matrix implementation
adjacency tables consist of header nodes (node information) and table nodes (Edge information), where each vertex corresponds to a table header node stored in an array. The following is a weighted graph:

Example 1: Each vertex in the adjacency list corresponds to a table header node stored in an array, and for simplification, each adjacency node structure contains only the next adjacent node number and edge right, which is programmed using the standard template vector. It can also be implemented by adjacency matrices, as follows:

/***** understand the realization of the edge information structure and adjacency list, and add some edges on the basis of implementation, and then use the adjacency matrix to realize the use of ERASE,PUSH_BACK,SETW *****/#include <iostream># Include <iomanip> #include <vector> #define INF-1//Set Infinity-1, which represents the borderless using namespace Std;int n;//edge information, Weights that contain connection node numbers and edges struct edge{int adjnodenum;int edgeweight;}; struct node{//node information int nodenum;char data;} Node[110];vector<edge> adjlist[110]; The adjacency list, which has a maximum of 110 nodes int adjmatrix[110][110];//adjacency matrix void initadjlist () {int i;for (i = 0; i < n; i++) adjlist[i].clear ();// Empty---> Build---> Specific actions edge tmp0[2], tmp1[2], tmp2, tmp3[3];tmp0[0].adjnodenum = 1; Tmp0[0].edgeweight = 1;tmp0[1].adjnodenum = 2; Tmp0[1].edgeweight = 4;node[0].data = ' A '; Node[0].nodenum = 0;adjlist[0].push_back (tmp0[0]); Adjlist[0].push_back (tmp0[1]); tmp1[0].adjnodenum = 2; Tmp1[0].edgeweight = 2;tmp1[1].adjnodenum = 3; Tmp1[1].edgeweight = 9;node[1].data = ' B '; Node[1].nodenum = 1;adjlist[1].push_back (tmp1[0]); Adjlist[1].push_back (tmp1[1]); tmp2.adjnodenum = 3; Tmp2.edgeweight = 6;node[2].data = ' D '; Node[2].nodenum = 2;adjlist[2].push_back (TMP2); tmp3[0].adjnodenum = 0; Tmp3[0].edgeweight = 3;tmp3[1].adjnodenum = 1; Tmp3[1].edgeweight = 5;tmp3[2].adjnodenum = 2; Tmp3[2].edgeweight = 8;adjlist[3].push_back (tmp3[0]); Adjlist[3].push_back (tmp3[1]); Adjlist[3].push_back (tmp3[2]); node[3].data = ' C '; Node[3].nodenum = 3;} void output () {int I, j;for (i = 0; i < n; i++) {cout << node[i].nodenum << setw (2) << node[i].data;for ( j = 0; J < Adjlist[i].size (); J + +) {cout << setw (6) << adjlist[i][j].adjnodenum << setw (2) << adjlist[i][j].edgeweight;} cout << SETW (9) << "NULL" << Endl;}} void Makechange () {cout << "make some changes......:\n"; Edge temp;temp.adjnodenum = 3; Temp.edgeweight = 5;adjlist[0].push_back (temp),//Add an element Adjlist[3].erase (Adjlist[3].begin () +1, adjlist[3] in adjacency table 0. Begin () +3);//Delete two elements in adjacency table 3}void Initmatrix () {int I, j;for (i = 0; i < n; i++) {for (j = 0; J < N; j + +) {Adjmatrix[i][j] = INF;} Adjmatrix[i][i] = 0;} ADJMATRIX[0][1] = 1; ADJMATRIX[0][2] = 4; ADJMATRIX[1][2] = 2;adjmatrix[1][3] = 9; ADJMATRIX[2][3] = 6; Adjmatrix[3][0] = 3;adjmatrix[3][1] = 5; ADJMATRIX[3][2] = 8;} void Output1 () {int I, j;cout << "Output the adjacency matrix:\n"; for (i = 0; i < n; i++) {for (j = 0; J < N; j + +) {if (j = = 0) cout << adjmatrix[i][j];else cout << setw (3) << adjmatrix[i][j];} cout << Endl;}} int main () {n = 4;initadjlist (); output (); Makechange (); output (); Initmatrix (); output1 (); return 0;}

The results of the program run as follows:



4), and the implementation of the check set
and set: Use a node in a tree to represent the numbers in a set, such as {1,2,3,4} and {5,6}, and then use the contents of each node to represent their parent nodes, such as Tree[n], then tree[1] = 1, tree[2] = 1, tree[6] = 5 ...
If you want to merge the two tree trees, you can make tree[5] = 1 into tree[5] = 1. As follows:

for the following special case, we need to make certain constraints and optimizations when looking for the root node of the tree, and set the parent node of the traversed element to the root, as follows:



Example 1: The realization of the check set

/**** implements and sets the array composition, find the root node, merge two sets, compression path ************************/#include <iostream> #include <iomanip>using namespace Std;int set[110];int tree[110];//uses a lookup function to find the root node of the tree where x is located int findRoot (int x) {if (tree[x] = = 1) return X;elsereturn FindRoot (Tree[x]);} Use the Find function of the compressed path to find the root node of the tree where x is located, and only compress X to root to find the path int findRoot1 (int x) {if (tree[x] = =-1) return x;else{int TMP = FINDROOT1 (tree[x ]); TREE[X] = Tmp;return tmp;//layer returns}}//using a non-recursive int findroot_ (int x) {while (tree[x]! =-1) x = Tree[x];return x;} int findroot_1 (int x) {int tmp = X;while (tree[x]! =-1) x = Tree[x];while (tree[tmp]! =-1) {tmp = tree[tmp]; TREE[TMP] = x;} TMP saves the parent node in a convenient while loop, and then changes the contents of the array to return x;} int main () {int N1, n2;//the number of elements in the collection cout << "Please input the numbers of the Set1 and the" the "set2:\n" while (Cin > > N1 >> n2) {int i = 0, j;//the array table of input sets 1 and 2, the first row represents the element, the second row represents the parent node of the element cout << "please input Set1" Second line was its Father node): \ n "; for (i = 0; i < N1; i++) Cin >> set[i];for (i = 0; i < N1; i++) Cin >> tree[set[i]];cout << "Please input Set2 (first line was node, second line was its Father node): \ n"; for (i = N1 ; I < N1 + N2; i++) Cin >> set[i];for (i = n1; I < N1 + N2; i++) cin >> tree[set[i]];//Enter an element in set 1 and set 2 to find the respective root node cout &LT;&L T  "Please input both nodes of the sets (and output its root node): \ n"; int sub1, sub2;cin >> sub1 >> sub2;cout << "It's root node is:" << findRoot (sub1) << "" << findRoot (SUB2) << endl;//merges collections 1 and 2, and Show cout << "Merge trees:\n";  TREE[FINDROOT1 (sub2)] = FINDROOT1 (SUB1); for (i = 0; i < n1 + N2; i++) cout << setw (2) <<set[i];cout <<  Endl;for (i = 0; i < n1 + N2; i++) cout << setw (2) << tree[set[i]];cout << endl;cout << "please Input the number of Set1 and the number of set2:\n ";}}

The results of the program run as follows:

Example 2: unblocked works

/**** Enter the number of towns N and the number of roads m, and then enter the town where each road is connected (the town is numbered from 1), and see at least a few more roads to connect all the towns; if you enter n and n=0 end input ***********//**** initialize N and look up the set, then each path is entered, The associated two towns are joined to the same and the collection, and finally by the Independent and check the number 1 is the answer *********************/#include <iostream>using namespace Std;int tree[ 1100];int findRoot (int x) {if (tree[x] = =-1) return x;else{int TMP = FindRoot (tree[x]); TREE[X] = Tmp;return tmp;}} int main () {int n, m;while (cin >> n && n!= 0) {cin >> m;int i;for (i = 1; I <= n; i++)//Initialize N and check set Tree[i  ] = -1;int A, b;for (i = m; I >= 1; i--) {//Handles M roads, merges and sets Cin >> a >> b;a = FindRoot (a); b = FindRoot (b); if (A! = b) tree[b] = A; The comparison must be made here first, and if a, B is the same, the root node will not be 1, resulting in a reduced total number of}int count = 0;for (i = 1; I <= n; i++)//Calculate the remaining independent and check set if (tree[i] = = 1) ++count;cou T << "need to build the number of roads is:" << count-1 << Endl;}

The results of the program run as follows:

Example 3:more is Better

/*** has 1000 0000 children, randomly choose friends, each time two people, and the relationship has a transitive, when the choice m, output maximum number of friends or 1**********************//*** ideas and smooth works similar, initialize and check set, For each selection and collection merge, due to the need to calculate the maximum number of elements, need to initialize each sum[i]=1, each merge to accumulate can **//*** first enter the relationship number m, and then enter the M group relationship ****/#include <iostream >using namespace std; #define NUM 10000001int tree[num];int sum[num];int findRoot (int x) {if (tree[x] = =-1) return X;else {int tmp = FindRoot (tree[x]); TREE[X] = Tmp;return tmp;}} int main () {int m;while (cin >> m && m! = 0) {int i;for (i = 1; i < num; i++) {tree[i] = 1; Sum[i] = 1;} int A, b;while (m--) {cin >> a >> b;a = FindRoot (a); b = FindRoot (b); if (A! = b) {Tree[b] = A; Sum[a] + = Sum[b];}} int max = 1;for (i = 1; i < num; i++) if (Sum[i] > max) max = sum[i];cout << "Maximum number of Friends is:" < ;< max << Endl;} return 0;}

The results of the program run as follows:



Graph theory (i): Dfs,bfs, adjacency list, and search set

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.