耳分解&双极定向&边三连通

一张无向图的最大独立集与最大简单环长度至少有一个 n

耳分解

无向图版本

定义

  1. 耳与开耳

    在无向图 G=(V,E) 中存在子图 G=(V,E),若简单路径或简单环 P:x1x2xd 满足 x1,xdV,x2,xd1V,则称 PG 关于 G 的耳,若 P 是简单路径,又称其为开耳。

  2. 对于无向连通图 G,若连通图序列 (G0,G1,Gd) 满足:

    • G0 是一个简单环或者一个点

    • Gi1Gi 的子图

    • Gi=(Vi,Ei),则 EiEi1 构成一个耳(开耳)

      则称 (G0,G1Gd) 为图 G 的耳分解(开耳分解)

定理

  1. 无向连通图 G 存在耳分解当且仅当 G 边双联通

    必要性:耳分解的流程中每个 Gi 都是边双联通的

    充分性:考虑 dfs 树,找到一条非树边 1x,令这个与树上路径组成的环为 G0

    假设现在已经生成了 Gi,找到一个点 v 满足 vVi,uVi,若 ViV 必然可以找到,然后将 v 子树内选择一条跨出子树的返祖边加上 u 到返祖边端点的路径 作为一个耳生成 Gi+1,由于边双连通不存在割点一定可以,至于最后多出来的非树边可以直接作为一个耳加入。

  2. 至少含有三个点的无自环无向连通图 G 存在开耳分解当且仅当 G 点双连通。

    证明是类似的,但是返祖边的另一个端点不能是 u,根据点双连通性显然成立。

有向图版本

定义类似,有性质有向图可耳分解当且仅当强连通

这也告诉我们一个边双可以通过定向变为强连通

构造方法:

建立 dfs 树,父亲向子节点定向,返祖边后代向祖先定向即可。


混合图可以被定向为强连通图,当且仅当以下条件同时满足:

  1. 将有向边看作无向边,图边双连通
  2. 将无向边看作两条有向边后图强连通

我们断言,选出任意无向边,一定存在一种定向方式使得定向后本性质仍然满足。

条件一显然仍然满足,下面论证条件二。

设当前图为 G,选出无向边 (u,v),删掉它后图为 G0,那么由条件二可知 G0u,v 至少是可达的,不妨设 u 可达 v,如果此时 v 可达 u 显然成立。

否则,图至多最终分裂为两个强连通分量,因为只断掉一条边,因此对于每个其他点 x,至少与 u,v 两者之一可达。

因此此时把边定向为 vu 就满足了。

双极定向

给定无向图 G=(V,E) 以及两个不同节点 s,t,以下四个命题等价:

  1. 加入 stG 点双连通
  2. G 的圆方树上所有方点都在一条链上
  3. 存在一种对 G 进行定向的方法使得得到一个 DAG,有且只有 s 没有入度,t 没有出度。
  4. 存在一个节点排列 pp1=s,pn=t,满足任意前缀和任意后缀的导出子图都是连通的。

1,2 显然等价,3,4 是有向图与拓扑序的关系,也显然等价。

注意加入边 st 后我们对图做开耳分解,根据可达性选择外部路径方向即可,这证明了 13

然后假设 4 成立,1 不成立,设一个割点 x(指加入边 (s,t) 后,由于 1 不成立因此图不点双连通),在消去它后 s,t 处于同一连通块且 x 也处于一个连通块之中,取出这个连通块在 p 中第一个和最后一个出现的值,这两者之间至少一个不是 x,那么根据前后缀连通又必须经过割点割点又不在则一定 4 不成立,矛盾。


实现方面:

考虑以 s 为根,求出每个节点的 low,我们只需要保留这一条返祖边。

提出 ts 的链,然后建立新图 G,对于每个非链上的点,在新图中建立边 fauu,id[lowu]u,然后按 st 的顺序遍历链,遍历到一个点就开始深搜新图,并按照 dfs 序作为双极定向里的 p 即可。

按照 p 的顺序可以得出原图每条边的方向。

边三连通

建立无向图的 dfs 树(非树边都是返祖边),将所有非树边随机赋权,定义树边的权值覆盖其的非树边权值异或和(树上差分)

如果一个边集的 xor=0,则说明是割集(充分条件)

dzy love Chinese

边三连通图定义为最小割集不小于 3 的连通无向图。

k 连通图性质:

  1. x,y 满足 k 连通则 y,x 满足
  2. x,yy,z 满足 k 连通则 x,z k 连通

考虑边权:

  1. 树边 (u,v) 边权为零或者边权等于某条非树边,uv 及其子树内的点不边三连通
  2. 两条树边 (u,v),(x,y) 边权相同,则必然为一条到根的链上的边,因此断掉这两条边后子树 v 减去子树 y 的部分被独立出去。

注意暴力删边是错误的

利用异或运算来简化判断。

对于情况 1,直接给子树 v 异或一个随机值。

对于情况 2,直接给子树 v,y 异或上一个相同值。

可以通过打标记和再次 dfs 实现。

并且注意到,我们自底向上判断时,对于边权相同的树边只需要保留最浅的一条即可,画图易证。

模版:

双极定向:

int Dfn[N],Low[N],Idx,in[N],f[N],rew[N];
vector<int>Lik;
bool dfs(int u,int fa){
    Dfn[u]=Low[u]=++Idx;rew[Idx]=u;int tag=(u==Ed);
    for(auto v:ne[u])if(v!=fa){
        if(!Dfn[v])tag|=dfs(v,u),Low[u]=min(Low[u],Low[v]),in[u]++,f[v]=u;
        else Low[u]=min(Low[u],Dfn[v]);
    }
    if(tag)Lik.push_back(u);
    return tag;
}
int p[N],tot,dev[N];
vector<int>de[N];
void bianli(int x){
    if(dev[x])return ;
    dev[x]=1;
    p[++tot]=x;
    for(auto y:de[x])bianli(y);
}
void to_direct(){
    /*双极定向,还需要有一个遍历的在里面*/
    St=col[St],Ed=col[Ed];
    dfs(St,0);
    queue<int>q;
    for(int i=1;i<=node;++i)if(!in[i])q.push(i);
    while(!q.empty()){
        int u=q.front();q.pop();
        if(u==Ed)continue;
        /*
        shift,这里还需要注意到这条特别的链
        */
        de[f[u]].push_back(u);
        de[rew[Low[u]]].push_back(u);
        if(f[u]){
            --in[f[u]];
            if(!in[f[u]])q.push(f[u]);
        }
    }
    reverse(Lik.begin(),Lik.end());
    for(auto x:Lik)bianli(x);
}

边三连通

posted @   spdarkle  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示