```#include <algorithm>
#include <cstdio>
#include <vector>

using namespace std;

// excerpt from Juergen Werner's graph library

typedef vector<int> VI;
typedef vector<VI> VVI;

void DFS_visit_push(VVI &a, VI &v, VI &color, int act)
{
color[act] = 1;
for (VI::iterator it = a[act].begin(); it != a[act].end(); ++it)
if (!color[*it])
DFS_visit_push(a, v, color, *it);
v.push_back(act);
}

/* I    a : unweighted graph                     */
/* RETURNS: topological order of vertices 0..n-1 */
VI Topological_sort(VVI &a)
{
VI topo, color(a.size(), 0);
for (int i=0; i<(int)a.size(); i++)
if (!color[i])
DFS_visit_push(a, topo, color, i);
reverse(topo.begin(), topo.end());
}

/* I    a : unweighted graph              */
/* RETURNS: strongly connected components */
VVI SCC(VVI &a)
{
VI toporder = Topological_sort(a);
VVI a_t(a.size()), scc;
for (int i=0; i<(int)a.size(); i++)
for (VI::iterator it = a[i].begin(); it != a[i].end(); ++it)
a_t[*it].push_back(i);
VI color(a.size(), 0);
for (VI::iterator it = toporder.begin(); it != toporder.end(); ++it)
if (!color[*it])
{
VI component;
DFS_visit_push(a_t, component, color, *it);
scc.push_back(component);
}
return scc;
}

// end of graph library

const int NODES = 1<<24;

int main() {
VVI a(NODES);
int from, to, edge_count = 0;
while (scanf(" %x %x ", &from, &to) == 2) {
a[from].push_back(to);
++edge_count;
}
printf("The graph has %d nodes and %d edges.\n", a.size(), edge_count);
// calculate strongly connected components
VVI scc = SCC(a);
printf("The graph has %d strongly connected components.\n", scc.size());
printf("The component sizes are:");
for (VVI::iterator it = scc.begin() ; it != scc.end() ; ++it)
printf(" %d", it->size());
printf("\n");
printf("The components are (one per line):\n");
for (VVI::iterator it = scc.begin() ; it != scc.end() ; ++it) {
for (VI::iterator jt = it->begin() ; jt != it->end() ; ++jt)
printf(" 0x%06x", *jt);
printf("\n");
}
return 0;
}

```