zoukankan      html  css  js  c++  java
  • Leetcode 685

    我写的代码比较丑陋,等会再放上来。

    在树中添加一条附加边,一共会有以下几种情况发生:

    第一种,只有环。这种情况下,把导致环路的边删除即可。由于附加边只有一条,所以环也只能有一个,所以发现环路时,立刻记下当时处理的边。

    第二种,有一个节点存在两个父节点,但是没有环路存在。此时删除后来的那个父节点对应那条边即可。

    第三种,既有环路,又有冲突。此时需要找出哪个父节点存在于环路中,并将对应边删除。

    注意图示只是一个简单的示例,你应该意识到某个节点还可以向外延伸出各种边。重点在于,我们需要记录【冲突的两条边】和【导致环路的一条边】。

    同时,因为树的父节点只能有一个,所以【导致冲突的边】是不被记录到树结构上的。

    具体到写代码,我们使用并查集。记父节点数组为 father,当前处理的边为 edges[i],边的两边节点为 <from, to>。

    >>> 当 Find(from) == to,我们认为这条边导致了环,记下当前边的 i 为 cycleIndex。

    >>> 当 Find(to) != to,我们认为 <from, to> 导致了冲突,并记下当前边的 i 为 conflictIndex。

    >>> 如果都不符合,正常地连接两个节点,father[to] = from。

    经过以上处理,我们就得到了【冲突的两条边】和【导致环路的一条边】。

     如果是第一种或者第二种情况,事情就好办多了。关键是,既有冲突又有环的情况下,如何才能知道冲突的两条边谁在环上呢?

    我自己采取的办法是,从两条边选出一条,然后递归地求其父节点。

    过程中,如果求到了根节点,那么这条边就不必删除。

    否则,一定会求到冲突的子节点(也就是上图中的 B 节点)。那么这条边就需要被删除。

    int p = edges[conflictIndex][0];
    bool isConflictEdge = false;            
        
    while(father[p] != -1){ // 我个人用-1代表根节点
        p = father[p];
        if(p == edges[conflictIndex][1]){
            isConflictEdge = true;
            break;
        }
    }

    最后,代码的话还是建议看官方题解的代码。

  • 相关阅读:
    第七十四节,css边框与背景
    php中strlen和{}的效率对比
    for循环++i效率
    php优化技巧
    mysql中group_concat函数用法
    mysql引擎互转问题
    array_column php 函数
    php-mysql结果集函数比较
    javaweb 要学习的东西
    Java 泛型和类型安全的容器
  • 原文地址:https://www.cnblogs.com/KakagouLT/p/13688393.html
Copyright © 2011-2022 走看看