首页 > 其他分享 >割边+割点 学习心得

割边+割点 学习心得

时间:2023-10-13 14:22:06浏览次数:39  
标签:int 学习心得 割边 tot 割点 ++ dfn low ins

先背诵 tarjan 板子

#include<bits/stdc++.h>  
using namespace std;  
#define N 10005  
#define M 100005  
int tot,first[N],nxt[M],to[M];  
void add(int x,int y){  
    nxt[++tot]=first[x];  
    first[x]=tot;  
    to[tot]=y;  
}  
int n,m;  
bool ins[N];  
int dfn[N],low[N],dfc,stk[N],stail,idx,siz;  
void tarjan(int x){  
    dfn[x]=low[x]=++dfc;  
    stk[++stail]=x;  
    ins[x]=1;  
    for(int e=first[x];e;e=nxt[e]){  
        if(!dfn[to[e]]){  
            tarjan(to[e]);  
            low[x]=min(low[x],low[to[e]]);  
        }else if(ins[to[e]]){  
            low[x]=min(low[x],dfn[to[e]]);  
        }  
    }  
    if(dfn[x]==low[x]){  
        siz=0;  
        while(stk[stail]!=x){  
            --stail;  
            ++siz;  
        }  
        --stail;  
        if(siz>=1)++idx;  
    }  
    return;  
}  
int main(){  
    memset(ins,0,sizeof ins);  
    int x,y;  
    scanf("%d %d",&n,&m);  
    for(int i=1;i<=m;++i){  
        scanf("%d %d",&x,&y);  
        add(x,y);  
    }  
    for(int i=1;i<=n;++i){  
        if(!dfn[i])tarjan(i);  
    }  
    printf("%d\n",idx);  
    return 0;  
}

割点

相当于在 tarjan 找完新点以后判断一下新的点能不能通过另一条路径走回来,如果不能,那就是割点。

image

如图所示,下面部分的点,除了红色路径以外就不能走回上面 \(dfn\le4\) 的部分了,因此浅蓝色的点是割点。

image

如图所示,如果加了一条蓝色边,那么绿色点就可以通过蓝色边走回来,因此绿色点的 \(low\) 一定小于等于 \(4\) ,即能回到浅蓝色点及其之前的点上去,因此浅蓝色点不是割点。

需要注意的是,每次遍历的根节点不适用于这套规则,需要特判。而根节点是割点的条件是 出度 \(\ge2\) ,很好理解。

/*  
  bug:low[u] **>= ** 而不是 > dfn[x],因为走得到自己也算。  
 */  
#include<bits/stdc++.h>  
using namespace std;  
#define N 20005  
#define M 200005  
int tot,fir[N],nxt[M],to[M];  
int n,m,ans;  
int dfn[N],low[N],stk[N],stl,idx,grp[N],spc[N],dfc,root;  
bool ins[N];  
void add(int x,int y){  
    nxt[++tot]=fir[x];  
    fir[x]=tot;  
    to[tot]=y;  
}  
void tarjan(int x,int fa){  
    dfn[x]=low[x]=++dfc;  
    ins[x]=true;  
    stk[++stl]=x;  
    int scnt=0;  
    for(int e=fir[x];e;e=nxt[e]){  
        int u=to[e];  
        if(u==fa)continue;  
        if(!dfn[u]){  
            ++scnt;  
            tarjan(u,x);  
            low[x]=min(low[x],low[u]);  
            if(low[u]>=dfn[x]&&x!=root){  
                spc[x]=1;  
            }  
        }else if(ins[u]){  
            low[x]=min(low[x],dfn[u]);  
        }  
    }  
    if(dfn[x]==low[x]){  
        for(int u;stk[stl]!=x;--stl){  
            u=stk[stl];  
            ins[u]=0;  
        }  
        ins[x]=0;  
        --stl;  
    }  
    if(x==root){  
        if(scnt>1)spc[x]=1;  
    }  
    return;  
}  
int main(){  
    int x,y;  
    scanf("%d %d",&n,&m);  
    for(int i=1;i<=m;++i){  
        scanf("%d %d",&x,&y);  
        add(x,y);  
        add(y,x);  
    }  
    for(int i=1;i<=n;++i){  
        if(!dfn[i]){  
            root=i;  
            tarjan(i,0);  
        }  
    }  
    for(int i=1;i<=n;++i){  
        if(spc[i])++ans;  
    }  
    printf("%d\n",ans);  
    for(int i=1;i<=n;++i){  
        if(spc[i])  
        printf("%d ",i);  
    }  
    return 0;  
}

割边

比割点多一个条件:

image

如图,割边不能让另一个边连到浅蓝色节点上,因此判断的条件不是 \(dfn_x \le low_x\) 而是 \(dfn_x < low_x\)

image

这样就可以了。

并且,算割边不用判断根节点,因为根节点不是一条边

#include<bits/stdc++.h>  
using namespace std;  
#define N 200  
#define M 10005  
int tot,fir[N],nxt[M],to[M];  
int dfn[N],dfc,low[N],idx,grp[N],stk[N],stl;  
pair<int,int>sln[N];  
int n,m,slc;  
bool ins[N];  
void add(int x,int y){  
    nxt[++tot]=fir[x];  
    fir[x]=tot;  
    to[tot]=y;  
}  
void tarjan(int x,int fa){  
    dfn[x]=low[x]=++dfc;  
    ins[x]=1;  
    stk[++stl]=x;  
    for(int e=fir[x];e;e=nxt[e]){  
        int u=to[e];  
        if(u==fa)continue;  
        if(!dfn[u]){  
            tarjan(u,x);  
            low[x]=min(low[x],low[u]);  
            if(low[u]>dfn[x])sln[++slc]=make_pair(min(x,u),max(x,u));  
        }else if(ins[u]){  
            low[x]=min(low[x],dfn[u]);  
        }  
    }  
    if(dfn[x]==low[x]){  
        for(int u;stk[stl]!=x;--stl){  
            u=stk[stl];  
            ins[u]=0;  
        }  
        ins[x]=0;  
        --stl;  
    }  
    return;  
}  
int main(){  
    int x,y;  
    memset(ins,0, sizeof ins);  
    scanf("%d %d",&n,&m);  
    for(int i=1;i<=m;++i){  
        scanf("%d %d",&x,&y);  
        add(x,y);  
        add(y,x);  
    }  
    for(int i=1;i<=n;++i){  
        if(!dfn[i])tarjan(i,0);  
    }  
    sort(sln+1,sln+slc+1);  
    for(int i=1;i<=slc;++i){  
        printf("%d %d\n",sln[i].first,sln[i].second);  
    }  
    return 0;  
}

标签:int,学习心得,割边,tot,割点,++,dfn,low,ins
From: https://www.cnblogs.com/DZhearMins/p/17762012.html

相关文章

  • 二分图匹配 - 学习心得
    就是跑匈牙利算法就行了,难点完全在于建图。模板水题Link#include<bits/stdc++.h>constintN=510;intn,m,e;intG[N][N],match[N];std::bitset<N>vis;namespaceBlackWhiteGraph{ inlinevoidInit(void){ scanf("%d%d",&n,&m); inta,t; for(regis......
  • MySQL数据库学习心得
    MySQL数据库是一个常用的关系型数据库管理系统,它由瑞典公司MySQLAB开发,后来被SunMicrosystems收购,最终被甲骨文公司(OracleCorporation)收购。MySQL数据库具有高效、稳定、可靠的特点,被广泛应用于Web开发、数据存储和管理等方面。一、安装和配置MySQL首先,您需要在您的计算机上安......
  • Tarjan 求割点和桥
    欢迎批评指正!前置芝士割点:对于一个点\(u\),若删除\(u\)会使当前无向图中连通分量增多,我们就称\(u\)为该图的割点。桥(割边):同理,对于一条边\((u,v)\),若删除\((u,v)\)会使当前无向图中连通分量增多,我们就称\((u,v)\)为该图的桥。Tarjan求强连通分量Tarjan求割点设......
  • 缩点+割点学习笔记
    缩点传送门根据题意:允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。所以我们可以考虑将可以相互到达的若干个点缩成一个点,以方便计算。下面讲如何实现:考虑\(dfs\),并且对点记录如下信息\(dfn\)(该点被遍历到的时间节点,即该点是第几个被遍历到的),\(low\)(可以追溯到......
  • 割点和割边
    \(x's\text{}son\inT(x)\)\(Isn't\text{}x's\text{}son\inT'(x)\)\(x\inCutpoint,y\inT(x),y\notinT'(x)\)。\(i's\text{dfsorder}\todfn_i\)$\min(dfn_{f_y,y\inT(x)})\tolow_x$\(low_{y......
  • ThreadLocal的学习心得
    ThreadLocal是Java提供的线程本地存储机制,可以实现多线程环境下数据的隔离。主要特点是:每个线程都有自己的实例副本,实现了线程的数据隔离。ThreadLocal中存储的值对其他线程都不可见。通过get()和set()来读写当前线程的实例副本,避免了线程安全问题。本地线程副本通过弱......
  • Syline6.5学习心得-web-创建几何对象
    通过实例说明如何在Skyline中创建圆、文本、多边形等几何要素,设置要素的颜色,要素提示,飞行到几何要素等功能。1.使用的接口    ICreator65:可以创建几何要素、颜色、位置、图层等等(具体请查看api)例如本篇所涉及的要素:CreatePosition,CreateColor,CreateCircle,CreateMessage......
  • C语言学习心得
    C语言学习心得auto变量和static变量auto变量:每次执行到该变量定义语句时,都会产生一个新的变量,并且重新对此初始化。注意:该关键字在C语言与C++中的语义不同,在C++中是用于变量类型自动推断。为了让类似下面的代码能够在VS2022中运行而不报错,autointa=1;要这样操作:打......
  • 割点 & 点双
    0.前言最抽象的一集马上就和昨天的搞混1.几个区别啥是强连通分量?有向图的东西!现在开始就踏进无向图的大门!2.性质割点:在一个无向连通图中,如果删去某个点后,图变成不连通图,则称该点为割点。点双连通:如果一个连通图(可以是一个子图)中不含割点,则称该图是点双连通的。点双连......
  • 【笔者感悟】笔者的学习心得【六】
    个人经历  任何心得写出来都需要个人经历,否则凭空想象真想不出来,然而有趣的是笔者这篇感悟并不是在工作中得出来的,而是在一个和软件开发完全不相干的领域中得到的灵感,昨晚EDG和TES鏖战五局,尽管最终EDG还是没能战胜自己的心魔TES,为什么,不得不说选手的战术执行得很差,但是EDG深厚......