#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int N = 10000 + 10; const int M = 50000 + 10; int n, m; int head1[N], tot1, head2[N], tot2; bool vis[N]; vector<int> v; //后序访问顺序的顶点列表 int cmp[N]; //所属强连通分量的拓扑序 struct Edge { int v, next; }e1[M], e2[M]; void init() { v.clear(); tot1 = tot2 = 0; memset(head1, -1, sizeof(head1)); memset(head2, -1, sizeof(head2)); } void adde(int *head, Edge *edge, int &tot, int u, int v) { edge[tot].v = v; edge[tot].next = head[u]; head[u] = tot++; } void dfs(int u) { vis[u] = true; for(int i=head1[u]; i!=-1; i=e1[i].next) { int v = e1[i].v; if(!vis[v]) dfs(v); } v.push_back(u); } void rdfs(int u, int k) { vis[u] = true; cmp[u] = k; for(int i=head2[u]; i!=-1; i=e2[i].next) { int v = e2[i].v; if(!vis[v]) rdfs(v, k); } } void disp(int *head, Edge *edge) //显示邻接表详细情况 { for(int i=1; i<=n; i++) { printf("%d : ", i); for(int j=head[i]; j!=-1; j=edge[j].next) cout<<edge[j].v<<" "; cout<<endl; } } int SCC()//查找出有多少个强连通分量 { memset(vis, 0, sizeof(vis)); for(int i=1; i<=n; i++) if(!vis[i]) dfs(i); memset(vis, 0, sizeof(vis)); int k=0; for(int i=v.size()-1; i>=0; i--) if(!vis[v[i]]) rdfs(v[i], k++); return k; } int main() { while(~scanf("%d%d", &n, &m)) { int u, v; init(); for(int i=0; i<m; i++) { scanf("%d%d", &u, &v); adde(head1, e1, tot1, u, v); //正向图 adde(head2, e2, tot2, v, u); //反向图 } disp(head1, e1); cout<<endl; disp(head2, e2); int ans = SCC(); printf("%d\n", ans); } return 0; } /* 6 7 1 2 2 3 2 4 3 4 4 5 5 3 5 6 */
时间: 2024-11-08 23:13:07