第五周 Redundant Connetion II

本文深入解析LeetCode上685题“Redundant Connection II”,探讨如何从有向图中移除一条边以恢复其根树结构。通过DFS算法识别三种可能的冗余边类型,并提供C++实现代码。

Redundant Connetion II

这一周还是图的问题
LeetCode上的685题:https://leetcode.com/problems/redundant-connection-ii/

题目

给出一个有向图和一条额外的边,该图是一个以1,2,…N为节点的根树,额外的边破坏了根树的性质。即给出N条边,找出一条额外边,使得剩下的边能组成根树,如果这样的边有复数条,返回输入中最后的边

Example1:

Input: [[1,2], [1,3], [2,3]]
Output: [2,3]
Explanation: The given directed graph will be like this:
  1
 / \
v   v
2-->3

Example 2 :

Input: [[1,2], [2,3], [3,4], [4,1], [1,5]]
Output: [4,1]
Explanation: The given directed graph will be like this:
5 <- 1 -> 2
     ^    |
     |    v
     4 <- 3

题解

我们知道如果有向图是一颗树时,使用dfs算法构造dfs生成树将不会遍历到已经遍历的节点。而当树中插入一条额外边时,使用dfs算法会产生下面的情况:
1.找到一条横跨边。如Example1
2.找到一条回边,出现环,图中有入度为0的"根"节点。如Example2
3.找到一条回边,出现环,图中没有入度为0的"根"节点。如下:

```
 5 -> 1 -> 2
 ^    |
 |    v
 4 <- 3
```

2,3的区别可以看成是2中回边没有指向根节点,3的情况则是回边指向了根节点。
在1,2中,必有两个节点指向同一个节点,为了恢复树结构,必须删除其中一条边。第1种情况下删除两条边都可以,选择输入中出现较晚的边即可。第2种情况下下必有一条边在环内,删除该边即可。
第3种情况下没有作为根的节点,删除环中任意一条边都可以。算法遍历(深度优先和宽度优先都可以)有向图找到环,再遍历环中所有边找到输入最晚出现的边。

代码

//节点的数据结构
struct Vertex {
    vector<int> child;		//子节点
    int parent;				//父节点
    int parent_num;		//父节点到该节点的边的编号
    bool isvisit;				//是否遍历
};

class Solution {
public:
    vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
        int _size = edges.size();
        queue<int> _queue;
        vector<Vertex> Vertexs(_size);
        vector<int> edge1, edge2;
        
		//遍历给出的所有边,更新每个节点的子节点,父节点等信息
        for (int i = 0; i < _size; i++) {
            auto &edge = edges[i];
            Vertexs[edge[0] - 1].child.push_back(edge[1]);
            if (Vertexs[edge[1] - 1].parent == 0) {
                Vertexs[edge[1] - 1].parent = edge[0];
                Vertexs[edge[1] - 1].parent_num = i;
            }
            else {	//当两个节点指向同一个节点,不记录较后出现的边,并把两条边按顺序记录在edge1,edge2
                edge1 = {Vertexs[edge[1] - 1].parent, edge[1]};
                edge2 = edge;
            }
        }

        for (auto &v : Vertexs) {
            //print(v.child);

            v.isvisit = false;
        }
        
        //在第1,2种情况下,必定返回edge1,edge2其中一个
        //第一种情况下,没有环,返回edge2
        //第二种情况下,必有一条边在环中,返回该边
        if (!edge1.empty()) {
            if(edge1[0] == findRoot(Vertexs, edge1[0]))
                return edge1;
            else
                return edge2;
        }


		//第三种情况
        _queue.push(1);
        Vertexs[0].isvisit = true;
        vector<int> max_edge;
        int n = 0, max_num;

		//宽度优先遍历
        while(!_queue.empty() || n != _size) {

            if (_queue.empty()) {
                for (int i = 0; i < _size; i++) {
                    if (!Vertexs[i].isvisit){
                        _queue.push(i + 1);
                        break;
                    }
                }
            }
            int v = _queue.front();
            //cout << "now" << v << endl;

            for (auto c : Vertexs[v - 1].child) {
                if (Vertexs[c - 1].isvisit) {	//若找到回边,记录并立刻跳出遍历
                    max_num = Vertexs[c - 1].parent_num;
                    max_edge = {v, c};
                    break;
                }
                else {
                    _queue.push(c);
                    Vertexs[c - 1].isvisit = true;
                }
            }

            if (!max_edge.empty()) {
                break;
            }

            _queue.pop();
            n++;

        }

		//由找出的回边通过父节点信息遍历整个环,找到出现最晚的环
        int cur_v = max_edge[1], next_v = max_edge[0];
        while(next_v != cur_v) {
            if (Vertexs[next_v - 1].parent_num > max_num) {
                max_num = Vertexs[next_v - 1].parent_num;
                max_edge = {Vertexs[next_v - 1].parent, next_v};
            }
            next_v = Vertexs[next_v - 1].parent;
        }

        return max_edge;


    }

	//如果一个节点在环中则返回自己,否则一直回溯到根节点的父节点,这里设置为0
    int findRoot(vector<Vertex>& Vertexs, int start) {
        int p = Vertexs[start - 1].parent;
        while (p != 0 && p != start) {
            p = Vertexs[p - 1].parent;
        }

        return p;
    }
};
我有两种类型的文本,主要是想获取connection等于号后面的文本,不需要$后面注释的类型,只需要逗号分隔,分号结束的数据,但是目前有两种文件写法,这一种是没有$后面的注释且读取数据与Connection在同一行如下面所示[Connection Manager] Object_Name = "Connection Manager Object"; Object_Class_Code = 0x06; Connection123 = 0x04030002,0x44640405,Param2,,Assem100,Param2,,Assem101,,,36,Assem102,"Exclusive Owner","","20 04 24 6E 2C 64 2C 65"; Connection2 = 0x02030002,0x44640305,Param2,0,,Param2,,Assem101,,,36,Assem102,"Input Only","","20 04 24 6E 2C EE 2C 65";还有一种就是读取数据不与Connction在同一行且有注释Connection Manager] Object_Name = "Connection Manager Object"; Object_Class_Code = 0x06; Connection1 = 0x04030002, $ 0-15 = supported transport classes $ 16 = trigger: cyclic $ 17 = trigger: change of state $ 18 = trigger: application $ 19-23 = trigger: reserved $ 24 = application type: listen-only $ 25 = application type: input-only $ 26 = application type: exclusive-owner $ 27 = application type: redundant-owner $ 28-30 = reserved $ 31 = Direction: Client = 0 / Server = 1 0x44640405, $ 0 = O->T fixed size supported $ 1 = O->T variable size supported $ 2 = T->O fixed size supported $ 3 = T->O variable size supported $ 4-5 = O->T number of bytes per slot (obsolete) $ 6-7 = T->O number of bytes per slot (obsolete) $ 8-10 = O->T Real time transfer format $ 11 = reserved $ 12-14 = T->O Real time transfer format $ 15 = reserved $ 16 = O->T connection type: NULL $ 17 = O->T connection type: MULTICAST $ 18 = O->T connection type: POINT2POINT $ 19 = O->T connection type: reserved $ 20 = T->O connection type: NULL $ 21 = T->O connection type: MULTICAST $ 22 = T->O connection type: POINT2POINT $ 23 = T->O connection type: reserved $ 24 = O->T priority: LOW $ 25 = O->T priority: HIGH $ 26 = O->T priority: SCHEDULED $ 27 = O->T priority: reserved $ 28 = T->O priority: LOW $ 29 = T->O priority: HIGH $ 30 = T->O priority: SCHEDULED $ 31 = T->O priority: reserved Param5,Param4,Assem100, $ O->T RPI, size, format Param5,Param3,Assem101, $ T->O RPI, size, format ,, $ proxy config size, format ,, $ target config size, format "Connection1", $ Connection Name "", $ help string "20 04 2C 64 2C 65"; $ Path Connection2 = 0x02030002, $ 0-15 = supported transport classes $ 16 = trigger: cyclic $ 17 = trigger: change of state $ 18 = trigger: application $ 19-23 = trigger: reserved $ 24 = application type: listen-only $ 25 = application type: input-only $ 26 = application type: exclusive-owner $ 27 = application type: redundant-owner $ 28-30 = reserved $ 31 = Direction: Client = 0 / Server = 1 0x44640305, $ 0 = O->T fixed size supported $ 1 = O->T variable size supported $ 2 = T->O fixed size supported $ 3 = T->O variable size supported $ 4-5 = O->T number of bytes per slot (obsolete) $ 6-7 = T->O number of bytes per slot (obsolete) $ 8-10 = O->T Real time transfer format $ 11 = reserved $ 12-14 = T->O Real time transfer format $ 15 = reserved $ 16 = O->T connection type: NULL $ 17 = O->T connection type: MULTICAST $ 18 = O->T connection type: POINT2POINT $ 19 = O->T connection type: reserved $ 20 = T->O connection type: NULL $ 21 = T->O connection type: MULTICAST $ 22 = T->O connection type: POINT2POINT $ 23 = T->O connection type: reserved $ 24 = O->T priority: LOW $ 25 = O->T priority: HIGH $ 26 = O->T priority: SCHEDULED $ 27 = O->T priority: reserved $ 28 = T->O priority: LOW $ 29 = T->O priority: HIGH $ 30 = T->O priority: SCHEDULED $ 31 = T->O priority: reserved Param5,0,, $ O->T RPI, size, format Param5,Param7,Assem1, $ T->O RPI, size, format ,, $ proxy config size, format ,, $ target config size, format "Tag Connection", $ Connection Name "", $ help string "SYMBOL_ANSI"; $ Path Connection3 = 0x02030002, $ 0-15 = supported transport classes $ 16 = trigger: cyclic $ 17 = trigger: change of state $ 18 = trigger: application $ 19-23 = trigger: reserved $ 24 = application type: listen-only $ 25 = application type: input-only $ 26 = application type: exclusive-owner $ 27 = application type: redundant-owner $ 28-30 = reserved $ 31 = Direction: Client = 0 / Server = 1 0x44640305, $ 0 = O->T fixed size supported $ 1 = O->T variable size supported $ 2 = T->O fixed size supported $ 3 = T->O variable size supported $ 4-5 = O->T number of bytes per slot (obsolete) $ 6-7 = T->O number of bytes per slot (obsolete) $ 8-10 = O->T Real time transfer format $ 11 = reserved $ 12-14 = T->O Real time transfer format $ 15 = reserved $ 16 = O->T connection type: NULL $ 17 = O->T connection type: MULTICAST $ 18 = O->T connection type: POINT2POINT $ 19 = O->T connection type: reserved $ 20 = T->O connection type: NULL $ 21 = T->O connection type: MULTICAST $ 22 = T->O connection type: POINT2POINT $ 23 = T->O connection type: reserved $ 24 = O->T priority: LOW $ 25 = O->T priority: HIGH $ 26 = O->T priority: SCHEDULED $ 27 = O->T priority: reserved $ 28 = T->O priority: LOW $ 29 = T->O priority: HIGH $ 30 = T->O priority: SCHEDULED $ 31 = T->O priority: reserved Param5,0,, $ O->T RPI, size, format Param5,Param3,Assem101, $ T->O RPI, size, format ,, $ proxy config size, format ,, $ target config size, format "Connection1_Input Only",$ Connection Name "", $ help string "20 04 2C C6 2C 65"; $ Path Connection4 = 0x01030002, $ 0-15 = supported transport classes $ 16 = trigger: cyclic $ 17 = trigger: change of state $ 18 = trigger: application $ 19-23 = trigger: reserved $ 24 = application type: listen-only $ 25 = application type: input-only $ 26 = application type: exclusive-owner $ 27 = application type: redundant-owner $ 28-30 = reserved $ 31 = Direction: Client = 0 / Server = 1 0x44240305, $ 0 = O->T fixed size supported $ 1 = O->T variable size supported $ 2 = T->O fixed size supported $ 3 = T->O variable size supported $ 4-5 = O->T number of bytes per slot (obsolete) $ 6-7 = T->O number of bytes per slot (obsolete) $ 8-10 = O->T Real time transfer format $ 11 = reserved $ 12-14 = T->O Real time transfer format $ 15 = reserved $ 16 = O->T connection type: NULL $ 17 = O->T connection type: MULTICAST $ 18 = O->T connection type: POINT2POINT $ 19 = O->T connection type: reserved $ 20 = T->O connection type: NULL $ 21 = T->O connection type: MULTICAST $ 22 = T->O connection type: POINT2POINT $ 23 = T->O connection type: reserved $ 24 = O->T priority: LOW $ 25 = O->T priority: HIGH $ 26 = O->T priority: SCHEDULED $ 27 = O->T priority: reserved $ 28 = T->O priority: LOW $ 29 = T->O priority: HIGH $ 30 = T->O priority: SCHEDULED $ 31 = T->O priority: reserved Param5,0,, $ O->T RPI, size, format Param5,Param3,Assem101, $ T->O RPI, size, format ,, $ proxy config size, format ,, $ target config size, format "Connection1_Listen Only",$ Connection Name "", $ help string "20 04 2C C7 2C 65"; $ Path 如何同时解析每一个连接点的数据 Connection3 = 0x01030002,0x44240305,Param2,0,,Param2,,Assem101,,,,,"Listen Only","","20 04 24 6F 2C ED 2C 65";
08-27
基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究(Matlab代码实现)内容概要:本文围绕“基于可靠性评估序贯蒙特卡洛模拟法的配电网可靠性评估研究”,介绍了利用Matlab代码实现配电网可靠性的仿真分析方法。重点采用序贯蒙特卡洛模拟法对配电网进行长时间段的状态抽样与统计,通过模拟系统元件的故障与修复过程,评估配电网的关键可靠性指标,如系统停电频率、停电持续时间、负荷点可靠性等。该方法能够有效处理复杂网络结构与设备时序特性,提升评估精度,适用于含分布式电源、电动汽车等新型负荷接入的现代配电网。文中提供了完整的Matlab实现代码与案例分析,便于复现和扩展应用。; 适合人群:具备电力系统基础知识和Matlab编程能力的高校研究生、科研人员及电力行业技术人员,尤其适合从事配电网规划、运行与可靠性分析相关工作的人员; 使用场景及目标:①掌握序贯蒙特卡洛模拟法在电力系统可靠性评估中的基本原理与实现流程;②学习如何通过Matlab构建配电网仿真模型并进行状态转移模拟;③应用于含新能源接入的复杂配电网可靠性定量评估与优化设计; 阅读建议:建议结合文中提供的Matlab代码逐段调试运行,理解状态抽样、故障判断、修复逻辑及指标统计的具体实现方式,同时可扩展至不同网络结构或加入更多不确定性因素进行深化研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值