Strongly Connected Componenet
namespace Graph
{
const int __=2e5+5;
int n,v[__];//点权
vectorG[__];
void init(int _n)
{
n=_n;
for(int i=1;i<=n;++i)
G[i].clear();
}
void add_edge(int x,int y)//有向边
{
G[x].push_back(y);
}
}
namespace SCC
{
const int __=2e5+5;
vectorG[__];//缩点后注意重边有影响使用set
int n,idx,dfn[__],low[__],bel[__],s[__];//栈
ll v[__];//缩点后的点权
int dfs(int x)
{
if(dfn[x])return dfn[x];
s[++*s]=x;
dfn[x]=low[x]=++idx;
for(int y:Graph::G[x])
if(!bel[y])
low[x]=min(low[x],dfs(y));
if(low[x]==dfn[x])
for(bel[x]=++n,v[n]=0;;--*s)
{
v[n]+=Graph::v[s[*s]];
if(s[*s]==x){--*s;break;}
else bel[s[*s]]=n;
}
return low[x];
}
void tarjan()//注意一个点的特判
{
idx=n=*s=0;
for(int i=1;i<=Graph::n;++i)
if(!dfn[i])dfs(i);
for(int i=1;i<=Graph::n;++i)
for(int y:Graph::G[i])
if(bel[i]!=bel[y])
G[bel[i]].push_back(bel[y]);
}
void clear()
{
for(int i=1;i<=Graph::n;++i)
{
dfn[i]=bel[i]=0;
G[i].clear();
}
}
void print()
{
for(int i=1;i<=Graph::n;++i)
printf("bel[%d]=%d\n",i,bel[i]);
for(int i=1;i<=n;++i)
{
printf("%d:",i);
for(int x:G[i])
pf(" %d",x);
putchar('\n');
}
}
}
割点(tarjan):
vectorG[105];
int low[105],dfn[105],cut[105],cont=1,ans=0;
void dfs(int fa,int x)
{
int son=0;
dfn[x]=low[x]=cont++;
int len=G[x].size();
for(int i=0; i=dfn[x]&&fa!=-1&&!cut[x])
{
cut[x]=1;
ans++;
}
}
else low[x]=min(low[x],dfn[nex]);
}
if(fa==-1&&son>1)
{
cut[x]=1;
ans++;
}
}
题目链接:Network(求割点个数)
tarjan:
vectorG[105];
int low[105],dfn[105],cut[105],cont=1,ans=0;
void dfs(int fa,int x)
{
int son=0;
dfn[x]=low[x]=cont++;
int len=G[x].size();
for(int i=0; i=dfn[x]&&fa!=-1&&!cut[x])
{
cut[x]=1;
ans++;
}
}
else low[x]=min(low[x],dfn[nex]);
}
if(fa==-1&&son>1)
{
cut[x]=1;
ans++;
}
}
void init(void)
{
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(cut,0,sizeof(cut));
cont=1; ans=0;
}
int main()
{
int n,x,y;
char ch;
while(~scanf("%d",&n)&&n)
{
init();
while(~scanf("%d",&x)&&x)
while((ch=getchar())!='\n')
{
scanf("%d",&y);
G[x].push_back(y);
G[y].push_back(x);
}
for(int i=1; i<=n; i++)
if(!dfn[i])dfs(-1,i);
printf("%d\n",ans);
for(int i=1; i<=n; i++)
G[i].clear();
}
return 0;
}
题目链接:割点(求割点个数以及割点)
tarjan:
int low[100005],dfn[100005],cut[100005],cont=1,ans=0;
vectorG[100005];
void dfs(int fa,int x)
{
int son=0;
dfn[x]=low[x]=cont++;
int len=G[x].size();
for(int i=0; i=dfn[x]&&fa!=-1&&!cut[x])
{
cut[x]=1;
ans++;
}
}
else low[x]=min(low[x],dfn[nex]);
}
if(fa==-1&&son>1)
{
cut[x]=1;
ans++;
}
}
int main()
{
int m,n,x,y;
scanf("%d%d",&n,&m);
for(int i=0; i
割边(tarjan):
int low[100005],dfn[100005],cont,ans;
vectorG[100005];
vector >bri;
void dfs(int fa,int x)
{
dfn[x]=low[x]=cont++;
int len=G[x].size();
for(int i=0; idfn[x])
{
if(nex>x)bri.push_back(make_pair(x,nex));
else bri.push_back(make_pair(nex,x));
ans++;
}
}
else low[x]=min(low[x],dfn[nex]);
}
}
题目链接:Critical Links
tarjan:
int low[100005],dfn[100005],cont,ans;
vectorG[100005];
vector >bri;
void dfs(int fa,int x)
{
dfn[x]=low[x]=cont++;
int len=G[x].size();
for(int i=0; idfn[x])
{
if(nex>x)bri.push_back(make_pair(x,nex));
else bri.push_back(make_pair(nex,x));
ans++;
}
}
else low[x]=min(low[x],dfn[nex]);
}
}
void init(void)
{
bri.clear();
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
cont=1;
ans=0;
}
int main()
{
int T,n,x,y,m;
while(~scanf("%d",&T))
{
init();
n=T;
while(T--)
{
scanf("%d (%d)",&x,&m);
for(int i=0; i
题目链接:割边与割点
tarjan:
int low[20005],dfn[20005],cut[20005],cont,ans;
vectorG[20005];
vector >bri;
void dfs(int fa,int x)
{
int son=0;
dfn[x]=low[x]=cont++;
int len=G[x].size();
for(int i=0; idfn[x]) //桥
if(nex>x)bri.push_back(make_pair(x,nex));
else bri.push_back(make_pair(nex,x));
if(low[nex]>=dfn[x]&&fa!=-1&&!cut[x]) //割点
{
ans++;
cut[x]=1;
}
}
else low[x]=min(low[x],dfn[nex]);
}
if(fa==-1&&son>1) //根节点割点判定
{
cut[x]=1;
ans++;
}
}
void init(void)
{
bri.clear();
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
cont=1;
ans=0;
}
int main()
{
int n,m,x,y;
init();
scanf("%d%d",&n,&m);
for(int i=0; i
强联通分量:
题目链接:迷宫城堡
Kosaraju:
vectorG[10005]; //正向边
vectorGr[10005]; //反向边
stackS;
int vis[10005];
int m,n;
void dfs_normal(int node)
{
vis[node]=1;
int len=G[node].size();
for(int i=0; i
题目链接:The Cow Prom
tarjan:
vectorG[50005];
int vis[50005];
int dfn[50005];
int low[50005];
int cont=1;
int n,m,ans=0;
stackS;
void dfs(int x)
{
dfn[x]=low[x]=cont++;
S.push(x);vis[x]=1;
int len=G[x].size();
for(int i=0; i1)ans++;
}
}
int main()
{
scanf("%d%d",&n,&m);
int x,y;
for(int i=0; i
双联通分量:
题目链接:边的双连通分量
tarjan:
int low[20005],dfn[20005],cont,ans;
int bel[20005],minn[20005];
vectorG[20005];
stackS;
void dfs(int fa,int x)
{
dfn[x]=low[x]=cont++;
S.push(x);
int len=G[x].size();
for(int i=0;i
题目链接:点的双连通分量
tarjan:
struct node
{
int nex,id;
} t;
struct edge
{
int now,nex,id;
} temp;
int low[20005],dfn[20005],bel[100005],minn[100005],cont,ans;
bool vis[100005];
stackS;
vectorG[20005];
void dfs(int fa,int x)
{
int son=0;
dfn[x]=low[x]=cont++;
int len=G[x].size();
for(int i=0; i=dfn[x]&&fa!=-1)||(son>1&&fa==-1))
{
ans++;
while(1)
{
temp=S.top();
S.pop();
bel[temp.id]=ans;
minn[ans]=min(minn[ans],temp.id);
vis[temp.id]=true;
if(temp.now==x&&temp.nex==nex)break;
}
}
}
else low[x]=min(low[x],dfn[nex]);
}
}
void init(int n)
{
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(bel,0,sizeof(bel));
memset(vis,false,sizeof(vis));
cont=1;
ans=0;
for(int i=1; i<=n; i++)
minn[i]=inf;
}
int main()
{
int n,m,x,y;
scanf("%d%d",&n,&m);
init(m);
for(int i=1; i<=m; i++)
{
scanf("%d%d",&x,&y);
t.id=i;
t.nex=y;
G[x].push_back(t);
t.nex=x;
G[y].push_back(t);
}
for(int i=1; i<=n; i++)
if(!dfn[i])dfs(-1,i);
ans++;
while(!S.empty())
{
temp=S.top();
S.pop();
bel[temp.id]=ans;
minn[ans]=min(minn[ans],temp.id);
}
printf("%d\n",ans);
for(int i=1; i<=m; i++)
printf("%d ",minn[bel[i]]);
return 0;
}