【总结】
【思考】
22-1 通过广度优先搜索对边进行分类
22-2 挂接点、桥以及双连通分支
a) G_π的根是G的挂接点,当且仅当在G_π中该根顶点至少有两个子女。
b) 设v是G_π中的某一非根顶点,证明v是G的挂接点当且仅当v有一个子顶点s,使得不存在从s或s的任何后裔顶点指向v的某个真祖先顶点的反向边。
c) 设low[v]=min(d[v],d[w]),d[w]:对v的后裔u,(u,w)是反向边
试说明对所有顶点v∈V,如何在O(E)时间内计算出low[v]。
----
资料:https://www.byvoid.com/blog/biconnect
----
const int maxn=1111;
const int maxm=5111;
int n,m;
struct EDGENODE{
int to;
int w;
bool cut;
int next;
};
struct SEDGE{
int u;
int v;
SEDGE(int uu=0,int vv=0){u=uu;v=vv;}
};
struct BCC_GRAPH{
int head[maxn];
EDGENODE edges[maxm];
int edge;
void init()
{
clr(head,-1);
edge=0;
}
void addedge(int u,int v,int c=0)
{
edges[edge].cut=0,edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++;
}
//BCC_Tarjan
int dfn[maxn],low[maxn],bccno[maxn],dfs_clock,bcc_cnt;
bool iscut[maxn];
vector<int>bcc[maxn];
stack<SEDGE>stk;
int dfs(int u,int fa)
{
int lowu=dfn[u]=++dfs_clock;
int child=0;
for (int i=head[u];i!=-1;i=edges[i].next)
{
int v=edges[i].to;
if (v==fa) continue;
SEDGE e=SEDGE(u,v);
if (!dfn[v])
{
stk.push(e);
child++;
int lowv=dfs(v,u);
lowu=min(lowu,lowv);
if (dfn[u]<=lowv) //cut 割点
{
iscut[u]=true;
//done 点双连通
bcc_cnt++;
bcc[bcc_cnt].clear();
SEDGE x;
do{
x=stk.top();
stk.pop();
if (bccno[x.u]!=bcc_cnt)
{
bcc[bcc_cnt].push_back(x.u);
bccno[x.u]=bcc_cnt;
}
if (bccno[x.v]!=bcc_cnt)
{
bcc[bcc_cnt].push_back(x.v);
bccno[x.v]=bcc_cnt;
}
}while (x.u!=u||x.v!=v);
//over
}
if (dfn[u]<lowv) //cut 桥
{
edges[i].cut=true;
edges[i^1].cut=true;
}
}
else if (dfn[v]<dfn[u])
{
stk.push(e);//done
lowu=min(lowu,dfn[v]);
}
}
if (fa<0&&child==1) iscut[u]=0;
low[u]=lowu;
return lowu;
}
void find_bcc(int n)
{
while (!stk.empty()) stk.pop();
clr(dfn,0);
clr(iscut,0);
clr(bccno,0);
dfs_clock=bcc_cnt=0;
REP_1(i,n)
{
if (!dfn[i]) dfs(i,-1);
}
}
//another
int block[maxn];
int vis[maxn];
int b_num;
void b_dfs(int u)
{
vis[u]=true;
block[u]=b_num;
for (int i=head[u];i!=-1;i=edges[i].next)
{
if (edges[i].cut) continue;
int v=edges[i].to;
if (!vis[v]) b_dfs(v);
}
}
void find_block(int n)
{
//find_block 边双连通
clr(block,0);
clr(vis,0);
b_num=0;
REP_1(i,n)
{
if (!vis[i])
{
b_num++;
b_dfs(i);
}
}
}
}solver;
----
22-3 欧拉回路
使用深度优先搜索,如果某条边被搜索到,则标记这条边为已选择,并且即使回溯也不能将当前边的状态改回未选择,每次回溯时,记录回溯路径。深度优先搜索结束后,记录的回溯路径就是欧拉回路。
----
void dfs(int u)
{
for (int i=1;i<=n;i++)
{
if (a[u][i])
{
a[u][i]=false;
a[i][u]=false;
dfs(i);
ans[++cnt]=i;
}
}
}
----
22-4 可达性
本文深入探讨了深度学习领域的关键算法,包括广度优先搜索在边分类的应用、挂接点和桥的概念解析,以及如何在O(E)时间内计算low[v]值。同时,文章还介绍了欧拉回路的深度优先搜索方法,通过实例展示了回路的发现过程。

8339

被折叠的 条评论
为什么被折叠?



