Targin——图的割边(桥)

1.割边是什么(桥)

割边,也称为桥,即在一个无向连通图中,如果删除某条边后,图不再连通。

例如:
在这里插入图片描述

2.求割边的方法

1.可以一次删除每一条边,然后用DFS或BFS或并查集检查图是否连通,如果删除一条边后导致图不再连通,那么刚才删除的边就是割边。
2.还是采用上次实现的求割点的方法:
将low[v] >= num[u] 修改为 low[v] > num[u] 即可,下面解释一下原因:
low[v] >= num[u]表示节点v在不经过父节点u可以回到父节点。
low[v] > num[u]表示节点v在不经过父节点u不能回到父节点。
倘若节点v不能回到祖先,也没有另外一条路回到父亲,那么u->v就是割边。

2.1实现

#include <iostream>
#include <vector>

using namespace std;

/*
* 测试用例
6 6(顶点数和边数)
1 4
1 3
4 2
3 2
2 5
5 6
*/ 



class Cut_point
{
private:
    int vertice = 0;//顶点数
    int edge = 0;//边数
    int root = 1;//记录根节点

    //0行0列不存储信息,graph[i][j]表示节点i到节点j的权值为graph[i][j]
    vector<vector<int>> graph;//存储图的信息

    //在所有的数组中下标0均不存值

    vector<int> num;//记录每个节点遍历的顺序(num[i] = j表示节点i是第j个被遍历的)
    vector<int> low;//记录节点不经过父顶点回溯的最早的节点(low[i] = j表示节点i最早回到j节点)
                    

    int index = 0;//记录num中的值

public:
    Cut_point(int x = 0, int y = 0) :vertice(x), edge(y)
    {
        graph.resize(vertice + 1);
        for (int i = 0;i <= vertice; i++)
        {
            graph[i].resize(vertice + 1,0);
        }

        num.resize(vertice + 1, 0);
        low.resize(vertice + 1, 0);
    }

    //图以及图相关的数据结构初始化
    void Init_Graph(void)
    {
        int u = 0, v = 0;
        for (int i = 0; i < edge; i++)
        {
            cin >> u >> v;
            graph[u][v] = 1;
            graph[v][u] = 1;//无向图的初始化,没有权重信息,初始化为1即可
        }
    }
   
    void Cut_point_By_DFS(int curernt,int father)
    {
        int child = 0;//记录current节点的汉字总数
        
        index++;//当前访问的顺序加1
        num[curernt] = index;//表示current节点是在第index被访问的
        low[curernt] = index;

        for (int i = 1; i <= vertice; i++)
        {
            if (graph[curernt][i] == 1)
            {
                //节点i还没有被访问过
                if (num[i] == 0)
                {
                    
                    Cut_point_By_DFS(i, curernt);//继续往下DFS

                    low[curernt] = min(low[curernt], low[i]); //更新current节点能够访问到的最早顶点的顺序

                    if (low[i] > num[curernt])//当前节点不是根节点,并且满足low[i] > num[current],则当前节点为割边
                    {
                       
                        cout << curernt << " --> " << i << endl;
                    }
                    
                }
                else if (i != father)
                {
                    low[curernt] = min(low[curernt], num[i]);
                }
            }
        }
    }
};

int main()
{
    int vertice = 0, edge = 0;//顶点数,边数

    
    cout << "请输入顶点数和边数:" << endl;
    cin >> vertice >> edge;
    Cut_point point(vertice,edge);

    cout << "请输入边的信息:" << endl;
    point.Init_Graph();

    cout << "割边为:";
    point.Cut_point_By_DFS(1, 1);//从1号顶点开始进行DFS,并且认为1号顶点是根节点
    
 
    return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值