求割点
void Tarjan(int u,int fa)
{
dfn[u]=low[u]=++index;
int child=0;
for(int i=0;i<mp[u].size();i++)
{
int v=mp[u][i];
if(!dfn[v])
{
Tarjan(v,u);
child++;
low[u]=min(low[u],low[v]);
if((u==1&&child>1)||(u!=1&&dfn[u]<=low[v]))
vis[u]=true;
}
else if(v!=fa)
low[u]=min(low[u],dfn[v]);
}
}
求割桥
void Tarjan(int u,int fa)
{
dfn[u]=low[u]=++index;
for(int i=0;i<mp[u].size();i++)
{
int v=mp[u][i];
if(!dfn[v])
{
Tarjan(v,u);
low[u]=min(low[u],low[v]);
if(dfn[u]<low[v])
e[cnt].u=u,e[cnt++].v=v;
}
else if(v!=fa)
low[u]=min(low[u],dfn[v]);
}
}
点双连通分量
struct node
{
int u,v;
}e[maxn];
int dfn[maxn],low[maxn],id[maxn],index,cnt;
int st[maxn],num;
int id[maxn];
bool iscut[maxn];
vector<int> bcc[maxn];
int bcc_cnt;
void Init()
{
memset(dfn,0,sizeof(dfn));
memset(id,0,sizeof(id));
index=num=bcc_cnt=0;
}
void Tarjan(int u,int pre)
{
dfn[u]=low[u]=++index;
int child=0;
for(int i=first[u];i!=-1;i=head[i])
{
int v=e[i].v;
if(!dfn[v])
{
st[++num]=i,child++;
Tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])
{
iscut[u]=true;
bcc[++bcc_cnt].clear();
while(1)
{
int top=st[num--];
if(id[e[top].u]!=bcc_cnt)
{
bcc[bcc_cnt].push_back(e[top].u);
id[e[top].u]=bcc_cnt;
}
if(id[e[top].v]!=bcc_cnt)
{
bcc[bcc_cnt].push_back(e[top].v);
id[e[top].v]=bcc_cnt;
}
if(e[top].u==u&&e[top].v==v)
break;
}
}
}
else if(dfn[v]<dfn[u]&&pre!=v)
{
st[++num]=i;
low[u]=min(low[u],dfn[v]);
}
}
if(pre<0&&child==1)
iscut[u]=false;
}
边双连通分量
struct node
{
int u,v;
}e[maxn];
int dfn[maxn],low[maxn],index;
int st[maxn],num;
bool iscute[maxn];
int id[maxn],bcc_cnt;
int first[maxn],head[maxn<<2],cnt;
void Tarjan(int u,int pre)
{
dfn[u]=low[u]=++index;
for(int i=first[u];i!=-1;i=head[i])
{
int v=e[i].v;
if(!dfn[v])
{
Tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u])
{
iscute[i]=iscute[i^1]=true;
}
}
else if(dfn[v]<dfn[u]&&v!=pre)
{
low[u]=min(low[u],dfn[v]);
}
}
}
void dfs(int u)
{
dfn[u]=1;
id[u]=bcc_cnt;
for(int i=first[u];i!=-1;i=head[i])
{
if(iscute[i])
continue;
int v=e[i].v;
if(!dfn[v])
dfs(v);
}
}
void solve()
{
memset(first,-1,sizeof(first));
memset(dfn,0,sizeof(dfn));
memset(id,0,sizeof(id));
memset(iscute,0,sizeof(iscute));
num=cnt=index=bcc_cnt=0;
for(int i=0;i<maxn;i++)
if(!dfn[i])
Tarjan(i,-1);
memset(dfn,0,sizeof(dfn));
for(int i=0;i<maxn;i++)
if(!dfn[i])
bcc_cnt++,dfs(i);
}
强连通分量
void Tarjan(int u)
{
dfn[u]=low[u]=++tot;
st[++index]=u;
vis[u]=true;
for(int i=0;i<mp[u].size();i++)
{
int v=mp[u][i];
if(!dfn[v])
{
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
int len=index;
cnt++;
while(st[index]!=u&&index!=0)
sum[st[index--]]=cnt;
sum[st[index--]]=cnt;
num[cnt]=len-index;
}
}
POJ 2186 Tarjan求强连通+缩点
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
#define inf 0x3f3f3f3f
#define PI acos(-1.0)
typedef long long ll;
const int maxn=1e4+10;
vector<int> mp[maxn];
int dfn[maxn],low[maxn],index,tot,st[maxn];
bool vis[maxn];
int cnt;
int num[maxn],out[maxn],sum[maxn];
void Tarjan(int u)
{
dfn[u]=low[u]=++tot;
st[++index]=u;
vis[u]=true;
for(int i=0;i<mp[u].size();i++)
{
int v=mp[u][i];
if(!dfn[v])
{
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
int len=index;
cnt++;
while(st[index]!=u&&index!=0)
sum[st[index--]]=cnt;
sum[st[index--]]=cnt;
num[cnt]=len-index;
}
}
int main()
{
int n,m;
cin >> n >> m;
for(int i=0;i<m;i++)
{
int a,b;
cin >> a >> b;
mp[a].push_back(b);
}
for(int i=1;i<=n;i++)
if(!dfn[i])
Tarjan(i);
for(int i=1;i<=n;i++)
{
for(int j=0;j<mp[i].size();j++)
{
int v=mp[i][j];
if(sum[i]!=sum[v])
out[sum[i]]++;
}
}
int ans=0;
for(int i=1;i<=cnt;i++)
{
if(!out[i])
{
if(ans)
{
cout << 0 << endl;
return 0;
}
ans=num[i];
}
}
cout << ans << endl;
return 0;
}