这是一个tarjan的模版题。我有个疑惑,看下面代码里的唯一一条注释。网上大都那么写,但这样写我总想不通到底有什么用,虽然两种写法都是对的,但是如果写成我这样的话,low值相同的点就在一个强联通分量中,不用开scc数组(看第二份代码)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
using namespace std;
const int maxN=1e4+5;
const int maxM=1e5+5;
int N,M;
int head[maxN],tol;
struct Graph
{
int to,next;
}path[maxM];
void add(int u,int v)
{
path[tol]={v,head[u]};
head[u]=tol++;
}
int dfn[maxN],low[maxN],scc[maxN],cnt;
int insta[maxN],tim;
stack<int>sta;
void tarjan(int u)
{
dfn[u]=low[u]=++tim;
sta.push(u);
insta[u]=1;
for(int i=head[u];i!=-1;i=path[i].next)
{
int v=path[i].to;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(insta[v])low[u]=min(low[u],low[v]);//--------------------------------------------这里网上大都写的low[u]=min(low[u],dfn[v])
}
if(dfn[u]==low[u])
{
int m;
cnt++;
do
{
m=sta.top();
sta.pop();
insta[m]=0;
scc[m]=cnt;
}while(u!=m);
}
}
int main()
{
while(~scanf("%d%d",&N,&M)&&(N+M))
{
int u,v;
memset(head,-1,sizeof(head));
memset(scc,0,sizeof(scc));
memset(dfn,0,sizeof(dfn));
cnt=tim=tol=0;
while(M--)
{
scanf("%d%d",&u,&v);
add(u,v);
}
tarjan(1);
int flag=0;
for(int i=2;i<=N;i++)if(scc[i]!=scc[1]){flag=1;break;}
if(flag)printf("No\n");
else printf("Yes\n");
}
return 0;
}
这个没有scc数组
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
using namespace std;
const int maxN=1e4+5;
const int maxM=1e5+5;
int N,M;
int head[maxN],tol;
struct Graph
{
int to,next;
}path[maxM];
void add(int u,int v)
{
path[tol]={v,head[u]};
head[u]=tol++;
}
int dfn[maxN],low[maxN];
int insta[maxN],tim;
stack<int>sta;
void tarjan(int u)
{
dfn[u]=low[u]=++tim;
sta.push(u);
insta[u]=1;
for(int i=head[u];i!=-1;i=path[i].next)
{
int v=path[i].to;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(insta[v])low[u]=min(low[u],low[v]);
}
if(dfn[u]==low[u])
{
int m;
do
{
m=sta.top();
sta.pop();
insta[m]=0;
}while(u!=m);
}
}
int main()
{
while(~scanf("%d%d",&N,&M)&&(N+M))
{
int u,v;
memset(head,-1,sizeof(head));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
tim=tol=0;
while(M--)
{
scanf("%d%d",&u,&v);
add(u,v);
}
tarjan(1);
int flag=0;
for(int i=2;i<=N;i++)if(low[i]!=low[1]){flag=1;break;}
if(flag)printf("No\n");
else printf("Yes\n");
}
return 0;
}