文章参考
割点:如果在图G中去掉一个顶点(自然同时去掉与该顶点相关联的所有边)后,该图的连通分支数增加,则称该顶点为G的割点(cut-vertex)。
/* memset(vis,0,sizeof(vis));*/
void tarjan(int x)
{
vis[x]=1;
dfn[x]=low[x]=++Time;
for(int i=first[i]; i!=-1; i=next[i])
{
if(!vis[v[i]])
{
tarjan(v[i]);
low[x] = min(low[x], low[v[i]]);
if(dfn[x]<=low[v[i]]) vis[x]++;
}
else
low[x] = min(low[x], dfn[v[i]]);
}
if( x==root&&vis[x]>2 || x!=root&&vis[x]>1)
vis[x]=2; //x是割点
else
vis[x]=1; //x不是割点
}
割边(桥):假设有连通图G,e是其中一条边,如果G-e是不连通的,则边e是图G的一条 割边。
/*
memset(vis,0,sizeof(vis));
memset(fa,0,sizeof(fa));
memset(judge,0,sizeof(judge));
*/
void tarjan(int x)
{
vis[x]=1;
dfn[x]=low[x]=++Time;
for(int i=first[i]; i!=-1; i=next[i])
{
if(!vis[v[i]])
{
fa[v[i]]=edge[i];
tarjan(v[i]);
low[x] = min(low[x],low[v[i]]);
}
else
if(fa[x]!=edge[i]&&low[x]>dfn[v[i]])
low[x]=dfn[v[i]];
}
if(fa[x]&&low[x]==dfn[x])
judge[fa[x]]=true;
}
强连通分量:有向图强连通分量在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向
路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通
分量(strongly connected components)。
/*
stack<int>st;
memset(vis,0,sizeof(vis));
memset(inst,0,sizeof(inst));
*/
void tarjan(int x)
{
vis[x]=1;
dfn[x]=low[x]=++Time;
inst[x]=1;
st.push(x);
for(int i=first[x];i!=-1;i=next[i])
{
if(!vis[v[i]])
{
tarjan(v[i]);
low[x]=min(low[x],low[v[i]]);
}
else if(in[v[i]])
low[x]=min(low[x],dfn[v[i]]);
}
if(low[x]==dfn[x])
{
num++;
do{
j=st.top();
st.pop();
scc[j]=num;
in[j]=0;
}
while(j!=x);
}
}
点双连通分量:在无向连通图中,如果删除该图的任何一个结点都不能改变该图的连通性,则该图为双连通的无向图。一个连通的无向图是双连通的,当且仅当它没有关键点。
/*memset(in,0,sizeof(in));
memset(vis,0,sizeof(vis));
*/
void tarjan(int x, int pre)
{
low[x]=dfn[x]=++tim;
vis[x]=1;
in[x]=1;
st.push(x);
for(int i=first[x];i;i=next[i])
{
if(!vis[v[i]])
{
tarjan(v[i],x);
low[x]=min(low[x],low[v[i]]);
if(dfn[x]<=low[v[i]])
{
int j;
num++; cnt=0;
do{
j=st.top(); st.pop();
cir[++cnt]=j;
in[j]=0;
belong[j]=num;
} while(j!=v[i]);
cir++[cnt]=x;
}
}
else if(v[i]!=pre&&in[v[i]])
low[x]=min(low[x],dfn[v[i]]);
}
}
LCA(最近公共祖先):对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u、v的祖先且x的深度尽可能大。
/*
int found(int x)
{
while(fa[x]!=x) x=fa[x];
return x;
}
memset(vis,0,sizeof(vis));
memset(r,0,sizeof(r));
for(int i=1;i<=n;i++)dis[i]=INF;//调用tarjan(a)时,disa=0;
*/
void tarjan(int x)
{
fa[x]=x;
vis[x]=1;
for(int i=first2[x];i!=-1;i=next2[i])
{
if(vis[v2[i]] && r[belong[i]]==0)
tem=found(v2[i]),
ans[belong[i]]=dis[x]+dis[v2[i]]-(dis[tem]<<1);
}
for(int i=first1[x];i!=-1;i=next1[i])
{
if(!vis[v1[i]])
{
dis[v1[i]]=dis[x]+w[i];
tarjan(v1[i]);
fa[v1[i]]=x;
}
}
}