#include const VMAX = 1000; const unseen = 0; typedef int boolean; const boolean false = 0, true = 1; inline int minimum(int a, int b) { return a < b ? a : b; } class Graph {private: struct node {int vertex; node* next;}; typedef node* Neighborlist; int id; int visit(int k, int p); Neighborlist z; public: Graph() /* initialize as an empty graph */ { z = new node; z->next = z; z->vertex = 0; V = E = 0; for (int i = 1; i <= VMAX; i++) adj[i] = z; } int V; int E; void addEdge(int a, int b); /* add an edge */ /* can do addEdge(x,x) to add an isolated vertex, the self edge will be ignored. */ int components; /* number of components */ boolean loops; /* true iff graph has loops. */ boolean biconnected; /* true iff graph has no articulation points. */ Neighborlist adj[VMAX]; int val[VMAX]; int df_search(int flag); /* set val[k] to index of visit to k in a depth first search. if flag == 1, return number of components. if flag == 2, return 1 if a loop exists, 0 if not. if flag == 3, return 1 if graph is biconnected, 0 if not. */ }; void Graph::addEdge(int a, int b) /* add an edge */ { V = (a > V) ? a : V; V = (b > V) ? b : V; if (a != b) { node* n = new node; n->vertex = b; n->next = adj[a]; adj[a] = n; n = new node; n->vertex = a; n->next = adj[b]; adj[b] = n; } } int main() { Graph G; /* initialize G */ int a, b; while (cin >> a >> b) G.addEdge(a, b); /* do stuff with G */ cout << G.df_search(1) << " components\n"; cout << G.df_search(2) << " loops\n"; cout << G.biconnected << " biconnected\n"; } int Graph::df_search(int flag) { int k; id = 0; components = 0; loops = false; biconnected = true; /* initialize val array */ for (k = 1; k <= V; k++) val[k] = unseen; /* after search, val[k] will hold the time unit at which k was visited */ /* search */ for (k = 1; k <= V; k++) if (val[k] == unseen) { components++; visit(k, k); } /* select return value */ switch (flag) { case 1: return components; case 2: return loops; case 3: return biconnected; default: return -1; } } int Graph::visit(int k, int p) /* k is vertex being visited, p is previously visited node. */ /* returns minimal dfs index reachable during dfs from k. */ { Neighborlist t; int m; int kmin; /* will be the minimum visit time of k and its neighbors. */ int nmin; /* will be the minimum visit time of any node reachable from a node reached from k during the search */ /* "see" node k */ nmin = kmin = val[k] = ++id; /* visit unseen neighbors */ for (t = adj[k]; t != z; t = t->next) { int n = t->vertex; /* a neighbor */ if (n == p) continue; if (val[n] == unseen) { m = visit(n, k); nmin = minimum(m, nmin); } else { kmin = minimum(val[n], kmin); } } if (nmin >= val[k]) biconnected = false; /* k is an articulation pt. */ if (kmin < val[k]) loops = true; /* k is on a loop */ return minimum(kmin, nmin); }