<pre name="code" class="cpp">#include<iostream> #include<cstdio> #include<sstream> #include<string> #include<vector> #include<list> #include<set> #include<map> #include<stack> #include<queue> #include<algorithm> #include<cmath> #pragma warning(disable:4996) using std::cin; using std::cout; using std::endl; using std::stringstream; using std::string; using std::vector; using std::list; using std::pair; using std::set; using std::multiset; using std::map; using std::multimap; using std::stack; using std::queue; class Graph { public: int vertex;//总结点数 int edge;//总边数 int SCC;//强联通分量数 vector<vector<int> >adjList;//邻接表 vector<int>represent_SCC;//每个强联通分量的代表元素 map<int, int>SCcomponents;//强连同分量 Graph() { vertex = edge = SCC = 0; } //curpath表示搜索的时间 void tarjan_sub(vector<int>&depth, vector<int>&ancestor, stack<int>&Stack, vector<bool>&visited, vector<bool>&inStack, const int &curvertex, int &time) { visited[curvertex] = true; inStack[curvertex] = true; depth[curvertex] = ancestor[curvertex] = time++; Stack.push(curvertex); for (size_t i = 0; i < adjList[curvertex].size(); i++) { if (!visited[adjList[curvertex][i]])//如果邻接点没被访问过 { tarjan_sub(depth, ancestor, Stack, visited, inStack, adjList[curvertex][i], time); ancestor[curvertex] = std::min(ancestor[curvertex], ancestor[adjList[curvertex][i]]); } else if (inStack[adjList[curvertex][i]])//如果邻接点在之前已经被加入堆栈中 { ancestor[curvertex] = std::min(ancestor[curvertex], depth[adjList[curvertex][i]]); } } if (ancestor[curvertex] == depth[curvertex]) { SCC++; represent_SCC.push_back(curvertex); while (true) { inStack[Stack.top()] = false; SCcomponents.insert({ Stack.top(),curvertex }); if (curvertex == Stack.top()) { Stack.pop(); break; } Stack.pop(); } } } void tarjan_main() { vector<int>depth(vertex + 1, 0), ancestor(vertex + 1, 0); stack<int>Stack; vector<bool>inStack(vertex + 1, false); vector<bool>visited(vertex + 1, false); int time = 1; for (int curvertex = 1; curvertex <= vertex; curvertex++) { if (!visited[curvertex]) { tarjan_sub(depth, ancestor, Stack, visited, inStack, curvertex, time); } } } pair<int, int>getDegree() { if (SCC == 1) { return{ 1,0 }; } vector<pair<int, int> >degree(vertex + 1);//first为出度,second为入度 set<pair<int, int> >Set; for (size_t i = 1; i < adjList.size(); i++) { for (size_t j = 0; j < adjList[i].size(); j++) { int initial = SCcomponents.find(i)->second; int terminal = SCcomponents.find(adjList[i][j])->second; if (initial != terminal&&Set.find({ initial,terminal }) == Set.end())//如果该边的两个点处于两个不同的强联通量中 { Set.insert({ initial,terminal }); degree[initial].first++; degree[terminal].second++; } } } int noOutDegree = 0, noInDegree = 0; for (size_t i = 0; i < represent_SCC.size(); i++) { if (!degree[represent_SCC[i]].first) { noOutDegree++; } if (!degree[represent_SCC[i]].second) { noInDegree++; } } return{ noInDegree,std::max(noInDegree,noOutDegree) }; } }; int main() { //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); int n; while (cin >> n) { Graph graph; graph.vertex = n; graph.adjList.resize(n + 1); for (int i = 1; i <= n; i++) { while (1) { int vertex; cin >> vertex; if (!vertex) { break; } graph.edge++; graph.adjList[i].push_back(vertex); } } graph.tarjan_main();//得到图的几个强联通子图 pair<int, int> result = graph.getDegree(); cout << result.first << endl; cout << result.second << endl; } return 0; }