Strongly connected components: in the graph G, if the two vertices vi,vj (VI>VJ) have a direction path from VI to VJ, and there is a forward path from VJ to VI, the two vertices are strongly connected. If there is strong connectivity to every two vertices of the graph G, the G is a strongly connected graph. A strongly connected sub-graph of a forward graph, called a strongly connected component.
Turning a graph into a strong connected graph requires adding the number of edges: first, the strong connected component of the original image is obtained, the indented point becomes a direction-free graph, the number of points with a new sumin of 0 is calculated and the number of points with a degree of 0 is sumout, the answer is Max (sumin,sumout).
Kosaraju algorithm:
1. First pass depth priority traversal of the original image, recording the departure time of each node num[i].
2. A second-pass depth-first traversal of the diagram with the opposite edge of the original, starting at the latest point in step (1) from the time of departure. In step (2) each search to a tree is a strong connected component hash[] The points on the same connected component are shrunk to a point.
3. The graph after the shrinking point makes up the Dag (directed acyclic graph), the number of trees is the number of strongly connected components.
#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>using namespace STD;Const intMAXN =10010;Const intMAXM =50050;structedgenode{intto;intNEXT1;intFrintNEXT2;} EDGES[MAXM];intHEAD1[MAXN],HEAD2[MAXN],VIS[MAXN];intNUM[MAXN],HASH[MAXN],COUNT[MAXN],OUTDEGREE[MAXN];intId//head1[],head2[] Separate original and inverse images//num[i] Record each node departure time//vis[i] is used to record whether a point has been accessed//count[sig] Count the number of points in the sig for each connected component//hash[cur] is used to indent point cur (all belonging to a sig) in the same Unicom component into a dot sigvoidAddedges (intUintV) {edges[id].to = v; Edges[id].next1 = Head1[u]; HEAD1[U] = ID; edges[id].fr = u; EDGES[ID].NEXT2 = Head2[v]; HEAD2[V] = id++;}//dfs First Pass, find out the time to record each node Num[i]voidDfsone (intCurint& Sig) {Vis[cur] =1; for(inti = head1[cur]; I! =-1; i = edges[i].next1) {if(!vis[edges[i].to]) Dfsone (Edges[i].to,sig); } Num[++sig] = cur;}//dfs second time, to find out the dual-link componentvoidDfstwo (intCurintSIG) {Vis[cur] =1; Hash[cur] = sig;//hash[] is used to indent points in the same Unicom component (all want a sig) into a single pointcount[sig]++;//count[] Count the number of points in each connected component, the sig is the number of strongly connected components for(inti = head2[cur]; I! =-1; i = edges[i].next2) {if(!vis[edges[i].fr]) Dfstwo (Edges[i].fr,sig);Else if(hash[edges[i].fr]! = Hash[cur])//outdegree Determine whether the new map points after the indentation of the degree, special topic requirementsOutdegree[hash[edges[i].fr]] =1; }}intKosaraju (intN) {intsig =0, ans;memset(Vis,0,sizeof(VIS));//First-time depth priority search for(inti =1; I <= N; ++i)//dfs obtaining a topological sequence num[] if(!vis[i]) Dfsone (I,sig);//sig is a strong connected number memset(Vis,0,sizeof(VIS));memset(Count,0,sizeof(Count));memset(Outdegree,0,sizeof(Outdegree));//second depth first search inti = sig; sig =0; for(; I >=1; I.)//Follow the topology sequence for a second DFS if(!vis[num[i]]) Dfstwo (Num[i],++sig);//algorithm end, the following are special topic requirements inttemp =0; for(inti =1; I <= sig; i++)//The new figure has only one point out of 0 to calculate a solution, special topic requirements if(!outdegree[i]) {temp++; ans = count[i]; }//printf ("$%d", temp); if(temp = =1)returnAnsElse return 0;}intMain () {intN,m,u,v; while(~scanf("%d%d", &n,&m)) {id =0;memset(head1,-1,sizeof(HEAD1));memset(head2,-1,sizeof(Head2)); for(inti =0; i < M; ++i) {scanf("%d%d", &u,&v); Addedges (U,V); }intAns = Kosaraju (N);printf("%d\n", ans); }return 0;}
Tarjan algorithm:
- Access a node that has not been accessed V;
- Initialize DFN[V] and low[v].
For all adjacency vertices of node v u:
- If you have not visited, go to step (2) while maintaining LOW[V].
- If accessed, but not deleted, maintain low[v].
If low[v] = = Dfn[v], then remove the corresponding strong connected components.
#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>using namespace STD;Const intMAXN =10010;Const intMAXM =50050;structedgenode{intto;intNext;} EDGES[MAXM];intHEAD[MAXN],VIS[MAXN],LOW[MAXN];intDfn[maxn],stack[maxn],outdegree[maxn],count[maxn],m,id;//dfn[v] Indicates the time at which the vertex v was accessed//low[v] Minimum value of low[u] and Low[v] for the non-deleted vertices that are adjacent to Vertex vvoidAddedges (intUintV) {edges[id].to = v; Edges[id].next = Head[u]; Head[u] = id++;}intTARBFS (intPosintLayint&SCC) {Vis[pos] =1; Low[pos] = lay;//Initial start timeDfn[pos] = lay;//Initial start timeSTACK[++M] = pos;//The current unhandled node into the stack, backtracking can determine whether the stack top to the node is the same strong connected component //If the current node is the root of a strongly connected component, its strong connectivity component must be the (remaining node) subtree of the root node for(inti = Head[pos]; I! =-1; i = edges[i].next)//Enumerate each edge{if(!vis[edges[i].to]) TARBFS (EDGES[I].TO,++LAY,SCC);if(Vis[edges[i].to] = =1) Low[pos] = min (low[pos],low[edges[i].to]); }//dfn[pos] = = Low[pos], the current vertex is a strongly connected component if(Dfn[pos] = = Low[pos])low[] The same node belongs to the same strong connected component .{++SCC;///number of strongly connected components Do{count[scc]++;//Record the number of points within each strongly connected componentLOW[STACK[M]] = SCC; VIS[STACK[M]] =2; } while(stack[m--]! = POS); }return 0;}intTarjan (intN) {intSCC =0, temp =0, ans, lay =1; m =0;memset(Vis,0,sizeof(VIS));memset(Low,0,sizeof(low));memset(DFN,0,sizeof(DFN)); for(inti =1; I <= N; ++i)//One time DFS to find strong connected components if(Vis[i] = =0) Tarbfs (I,LAY,SCC);//SCC The number of strongly connected components //below for special topic requirements, if there is only one point with an entry level of 0, then get for(inti =1; I <= N; ++i) { for(intj = Head[i]; J! =-1; j = edges[j].next)if(Low[i]! = low[edges[j].to]) {Outdegree[low[i]] =1;//marks a point with a non-0 entry level Break;/ * outdegree[low[i]]++; indegree[low[edges[j].to]]++; Record in and out of 0 points */} } for(inti =1; I <= SCC; ++i) {if(! outdegree[i])//Get the number of points that are not 0 in degrees{if(++temp >1) Break; ans = count[i]; } }if(Temp! =1)return 0;returnAns;}intMain () {intN,m,u,v; while(~scanf("%d%d", &n,&m)) {memset(head,-1,sizeof(Head));memset(Outdegree,0,sizeof(Outdegree));memset(Count,0,sizeof(Count)); ID =0; for(inti =0; i < M; ++i) {scanf("%d%d", &u,&v); Addedges (U,V); }intAns = Tarjan (N);printf("%d\n", ans); }return 0;}
Strongly connected components Kosaraju, Tarjan "Templates"