割点和桥的模板(割点和割边)

(1)割点与桥(割边)的定义(只存在于无向图)

割点:无向连通图中,去掉一个顶点及和它相邻的所有边,图中的连通分量数增加,则该顶点称为割点。

桥(割边):无向联通图中,去掉一条边,图中的连通分量数增加,则这条边,称为桥或者割边。

(2)割点与桥(割边)的关系

有割点不一定有桥,有桥一定存在割点;桥一定是割点依附的边。

(3)判断是否为割点

情况1:该点为根节点,那只要子节点数目超过1,那就是割点。

情况2:如果该点不为根节点,那只要这个节点的子节点不能够到达祖节点,那也是割点。

(4)判断是否为割边

只有满足此点有父亲节点并且不能回到自己的祖先。

 

(1)(求割点的模板)

题目描述

给出一个n个点,m条边的无向图,求图的割点。

输入格式

第一行输入n,m。下面m行每行输入x,y表示x到y有一条边

输出格式

第一行输出割点个数

第二行按照节点编号从小到大输出节点,用空格隔开

输入输出样例

输入 

6 7
1 2
1 3
1 4
2 5
3 5
4 5
5 6

输出 

1 
5

(割点模板)代码:

#include
#include
#define N 200010
#define M 20005
#include
using namespace std;
int net[N],first[M],to[N];//邻接表数组
int low[M],dfn[M],w[M],h[M];//tanjar数组
int n,m,x,y,cnt,num,cot;//需要用的变量
void init()
{
    cnt=1,num=0,cot=0;
    memset(first,-1,sizeof(first));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(w,0,sizeof(w));
}
void build_bian(int x,int y)//用邻接表双向建边
{
    to[cnt]=y;
    net[cnt]=first[x];
    first[x]=cnt++;
}
void tarjan(int x,int root,int father)//分别表示当前节点,根节点,父亲节点。
{
    low[x]=dfn[x]=++num;
    int child=0;
    for(int i=first[x]; i!=-1; i=net[i])
    {
        child++;//记录根节点的子节点数目。
        int k=to[i];
        if(dfn[k]==0)//表示k点没有被访问过
        {
            tarjan(k,root,x);
            low[x]=min(low[x],low[k]);
            if(x==root&&child>1)//如果该点为根节点且还2个及以上的子节点
                w[cot++]=x;
            if(x!=root&&low[k]>=dfn[x])//如果该子节点不能到达祖先节点
                w[cot++]=x;
        }
        else if(k!=father)//防止回到父亲节点
            low[x]=min(low[x],dfn[k]);
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        init();
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d",&x,&y);
            build_bian(x,y);
            build_bian(y,x);
        }
        for(int i=1; i<=n; i++)
            if(dfn[i]==0)
                tarjan(i,i,i);
        sort(w,w+cot);
        w[cot]=-1;
        int sum=0;
        for(int i=0; i

(2)(求割边的模板)

题目描述

因为某国被某红色政权残酷的高压暴力统治。美国派出将军uim,对该国进行战略性措施,以解救涂炭的生灵。

该国有n个城市,这些城市以铁路相连。任意两个城市都可以通过铁路直接或者间接到达。

uim发现有些铁路被毁坏之后,某两个城市无法互相通过铁路到达。这样的铁路就被称为key road。

uim为了尽快使该国的物流系统瘫痪,希望炸毁铁路,以达到存在某两个城市无法互相通过铁路到达的效果。

然而,只有一发炮弹(美国国会不给钱了)。所以,他能轰炸哪一条铁路呢?

输入格式

第一行n,m(1<=n<=150, 1<=m<=5000),分别表示有n个城市,总共m条铁路。

以下m行,每行两个整数a, b,表示城市a和城市b之间有铁路直接连接。

输出格式

输出有若干行。

每行包含两个数字a,b(a是key road。

请注意:输出时,所有的数对必须按照a从小到大排序输出;如果a相同,则根据b从小到大排序。

输入输出样例

输入 

6 6
1 2
2 3
2 4
3 5
4 5
5 6

输出 

1 2
5 6

(割桥模板)代码:

#include
#include
#define N 200
#define M 12000
#include
using namespace std;
int low[N],dfn[N];//tanjar数组
int first[N],net[M],to[M];//邻接表数组
int n,m,num,cnt,cot,fa[N];//需要用的变量
struct node
{
    int x,y;
} q[M];
bool cmp(node a,node b)
{
    if(a.x==b.x)
        return a.ydfn[fa[i]])//只有满足此点有父亲节点并且不能回到自己的祖先。
        {
            if(i>fa[i])
                q[cot].x=fa[i],q[cot++].y=i;
            else
                q[cot].x=i,q[cot++].y=fa[i];
        }
    sort(q,q+cot,cmp);
    q[cot].x=-1,q[cot].y=-1;
    for(int i=0; i

 

你可能感兴趣的:(图论)