求强连通量,为1输出Yes否则No
Tarjan算法模板
具体讲解:https://www.byvoid.com/zht/blog/scc-tarjan
#include "stdio.h"
#include "string.h"
struct Edge
{
int v,next;
}edge[100010];
int head[10010],stack[10010],dfn[10010],low[10010];
// stack栈; dfn深搜次序数组;low结点或者子树节点所能追溯到的最早栈中的标记数组
int instack[10010];
// 标记是否还在栈中
int n,m,cnt,scnt,tot,top;
void init()
{
cnt=0;
scnt=top=tot=0; // 初始化连通分量标号,栈顶指针,次序计数
memset(head,-1,sizeof(head));
memset(dfn,0,sizeof(dfn)); // 结点搜索的次序编号数组
}
void add(int u,int v)
{
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
}
void Tarjan(int w)
{
int i,v,t;
dfn[w]=low[w]=++tot;
instack[w]=1;
stack[top++]=w;
for (i=head[w];i!=-1;i=edge[i].next)
{
v=edge[i].v;
if (dfn[v]==0)
{
Tarjan(v);
if (low[w]>low[v]) // 更新结点W所能到达的最小次数层
low[w]=low[v];
}
else
if (instack[v] && dfn[v]<low[w])
low[w]=dfn[v];
}
if (dfn[w]==low[w]) // 如果结点W是强连通分量的根
{
scnt++; // 连通分量标号+1
do
{
t=stack[--top]; // 退栈
instack[t]=0;
}while (t!=w);
}
}
void solve()
{
int i;
for (i=1;i<=n;i++)
if (dfn[i]==0)
Tarjan(i);
}
int main()
{
int u,v;
while (scanf("%d%d",&n,&m)!=EOF)
{
if (n+m==0) break;
init();
while (m--)
{
scanf("%d%d",&u,&v);
add(u,v);
}
solve();
if (scnt==1) printf("Yes\n");
else printf("No\n");
}
return 0;
}