【题目描述】:
有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量(strongly connected components)。
现在给出一个有向图。结点个数N(<=1000)(编号1~N),边数M(<=5000)。请你按照从小到大的顺序输出最大的强连通分量结点编号。
【输入描述】:
第一行N和M 以下M行,每行两个空格隔开的整数表示一条有向边;
【输出描述】:
输出一行,最大的强连通分量的结点(由小到大输出)
【样例输入】:
10 20
2 2
5 3
8 5
3 4
8 7
10 10
10 6
7 7
2 8
3 2
8 1
3 8
1 7
8 10
7 5
6 4
9 2
8 6
7 5
1 8
【样例输出】:
1 2 3 5 7 8
【时间限制、数据范围及描述】:
时间:1s 空间:256M
N<=1000, M<=5000
题解:有向图滴强连通分量(tarjan做法
#include<cstdio> #include<iostream> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> #include<bits/stdc++.h> typedef long long ll; using namespace std; const int N=10005; int yc,a[N],n,m,cnt,x,y; struct node{ int to; int next; }e[N]; int ans,head[N],dfn[N],vis[N],low[N],tot,b[N]; void add(int x,int y){ e[++cnt].to=y; e[cnt].next=head[x]; head[x]=cnt; } stack<int>s; void tarjan(int x){ dfn[x]=low[x]=++tot; s.push(x); vis[x]=1; for(int i=head[x];i;i=e[i].next){ int v=e[i].to; if(!dfn[v]) { tarjan(v); low[x]=min(low[x],low[v]); } //未被访问过 else if(vis[v]) low[x]=min(low[x],dfn[v]); //访问过 } if(low[x]>=dfn[x]){ ans++; do{ y=s.top(); vis[y]=0; b[y]=ans; s.pop(); }while(y!=x); } } int main(){ scanf("%d %d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d %d",&x,&y); add(x,y); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++){ a[b[i]]++; if(a[b[i]]>a[yc]) yc=b[i]; } for(int i=1;i<=n;i++) if(b[i]==yc) printf("%d ",i); return 0; }