SCC指的是强连通分量,求SCC有三种高效的算法,即,他们的复杂度都是
,但Kosaraju要差一点。
算法:
hdu 1269
一个有向图,有n个点和m条边,判断整个图是否强连通,如果是输出,否则输出
。
手写一个栈,用的也行,我是用向前星存有向图。
code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=10005,maxm=100005;
int cnt;//强连通分量(SCC)的个数
int low[maxn],num[maxn],dfn;
int sccno[maxn],zhan[maxn],top;
int head[maxn],Next[maxm],to[maxm],tot;
inline void add(int u,int v) {
to[tot]=v;
Next[tot]=head[u];
head[u]=tot;
}
void dfs(int u) {
zhan[top++]=u;//u进栈
low[u]=num[u]=++dfn;
for(int i=head[u];i;i=Next[i]) {
int v=to[i];
if(!num[v]) {
dfs(v);//访问到DFS的最后一层,是最后一个SCC,或者是一个SCC的最后一个元素
low[u]=min(low[v],low[u]);//他可能有多个儿子,儿子如果和它不是一个SCC,
//只有儿子和它是一个SCC,low[v]才会小于等于low[u]
}//为访问过的点,继续DFS
else if(!sccno[v])
low[u]=min(low[u],num[v]);
//访问过的点可能是已经处理过的SCC上的点(还可能有重边)
}
if(low[u]==num[u]) {
++cnt;
while(1){
int v=zhan[--top];
sccno[v]=cnt;
if(u==v) break;//栈底的点是SCC的祖先,它low[u]==num[u]
}
}
}
void Tarjan(int n) {
cnt=top=dfn=0;
fill(sccno,sccno+maxn,0);
fill(num,num+maxn,0);
fill(low,low+maxn,0);
for(int i=1;i<=n;++i) if(!num[i])
dfs(i);
}
int main() {
int n,m,u,v;
while(scanf("%d%d",&n,&m),n) {
fill(head,head+maxn,0);
for( tot=1;tot<=m;++tot ) {
scanf("%d%d",&u,&v);
add(u,v);
}
Tarjan(n);
printf("%s\n",cnt==1?"Yes":"No");
}
return 0;
} 
京公网安备 11010502036488号