图的割点算法_割线和切线的区别「建议收藏」

图的割点算法_割线和切线的区别「建议收藏」图的割点、割线问题,代码实现,邻接矩阵和邻接链表_图内一点割线

图的割点算法_割线和切线的区别「建议收藏」"

图的割点问题

邻接矩阵表示图

package com.hyl.algorithm.other;

import java.util.Arrays;

import com.hyl.algorithm.search.base.SearchIntf;
import com.hyl.algorithm.search.base.SearchIntfFactory;

/** * 寻找图的割点 * <p> * * @author Hyl * @version V 0.1 * @since 0.1 2020-07-01 05:15 */
public class CutPoint implements SearchIntf { 
   

    private ArrayGraph graph;
    private int n, m, root, start, timestamp;

    private int[] num;
    private int[] low;
    private int[] book;

    @Override
    public void init() { 
   
        // 图
        // 1
        // / \
        // 4 3
        // \ /
        // 2
        // / \
        // 5 - 6
        n = 6;
        m = 7;
        graph = new ArrayGraph(n);
        graph.addUndirected(1, 3, 1);
        graph.addUndirected(1, 4, 1);
        graph.addUndirected(2, 3, 1);
        graph.addUndirected(2, 4, 1);
        graph.addUndirected(2, 5, 1);
        graph.addUndirected(2, 6, 1);
        graph.addUndirected(5, 6, 1);
        num = new int[n + 1];
        low = new int[n + 1];
        book = new int[n + 1];

        root = start = 1;
        timestamp = 0;

    }

    @Override
    public void find() { 
   
        dfs(start, root);
    }

    /** * 深度优先--割点算法 * @param cur 当前结点 * @param father 父结点 */
    private void dfs(int cur, int father) { 
   

        // 儿子数
        int child = 0;
        // 时间戳累加
        timestamp++;
        // 登记时间戳
        num[cur] = timestamp;
        low[cur] = timestamp;
        // 遍历连通结点
        for (int i = 1; i <= 6; i++) { 
   
            // 判断连通
            if (graph.getPath(cur, i) == 1) { 
   
                // 时间戳等于0表示没有被访问过
                if (num[i] == 0) { 
   
                    // 确定父子关系,儿子数加一
                    child++;
                    // 递归
                    dfs(i, cur);
                    // 递归完成,树已经形成,子结点和当前结点中使用能访问的较小时间戳
                    low[cur] = Math.min(low[cur], low[i]);
                    // 判定是否是割点,如果不是根结点,子结点能访问最小时间戳大于等于当前时间戳
                    if (cur != root && low[i] >= num[cur]) { 
   
                        book[cur] = 1;
                    }
                    // 如果是根结点有两个儿子,就是可以确定是割点
                    if (cur == root && child == 2) { 
   
                        book[cur] = 1;
                    }
                } else if (i != father) { 
   
                    // 没有搜索到就已经有时间戳了,还不是父结点,说明在没有经过父结点就已经访问过,使用最小时间戳
                    low[cur] = Math.min(low[cur], num[i]);
                }
            }
        }

    }

    @Override
    public void print() { 
   
        graph.print();
        System.out.println(Arrays.toString(num));
        System.out.println(Arrays.toString(low));
        System.out.println(Arrays.toString(book));
    }

    public static void main(String[] args) { 
   
        SearchIntfFactory.produce(CutPoint.class);
    }

}

图的割线问题

邻接表表示图

package com.hyl.algorithm.other;

import java.util.Arrays;

import com.hyl.algorithm.search.base.SearchIntf;
import com.hyl.algorithm.search.base.SearchIntfFactory;

/** * 图的割边问题 * <p> * * @author Hyl * @version V 0.1 * @since 0.1 2020-07-01 12:07 */
public class CutLine implements SearchIntf { 
   

    private LinkedGraph graph;
    private int n, m, start, root, timestamp;
    private int[] num, low;
    private int[][] lines;
    private int size;

    @Override
    public void init() { 
   
        // 图
        // 1
        // / \
        // 4 3
        // \ /
        // 2
        // / 
        // 5 - 6
        n = 6;
        m = 6;
        graph = new LinkedGraph(n, m);
        graph.addUndirected(1, 3, 1);
        graph.addUndirected(1, 4, 1);
        graph.addUndirected(2, 3, 1);
        graph.addUndirected(2, 4, 1);
        graph.addUndirected(2, 5, 1);
        graph.addUndirected(5, 6, 1);
        num = new int[n + 1];
        low = new int[n + 1];

        lines = new int[m][2];
        size = 0;
        root = start = 1;
        timestamp = 0;
    }

    @Override
    public void find() { 
   
        dfs(start, root);
    }

    private void dfs(int cur, int father) { 
   

        timestamp++;
        num[cur] = timestamp;
        low[cur] = timestamp;

        int index = graph.first[cur];
        while (index != -1) { 
   
            // 没有被访问过
            if (num[graph.v[index]] == 0) { 
   
                dfs(graph.v[index], cur);
                low[cur] = Math.min(low[cur], low[graph.v[index]]);
                // 相对割点问题,>= 改为 >,表示连父节点也无法返回
                if (low[graph.v[index]] > num[cur]) { 
   
                    lines[size][0] = cur;
                    lines[size][1] = graph.v[index];
                    size++;
                }
            } else if (graph.v[index] != father) { 
   
                // 可以被访问到,并不是父结点
                low[cur] = Math.min(low[cur], num[graph.v[index]]);
            }

            index = graph.next[index];
        }

    }

    @Override
    public void print() { 
   
        graph.printLines();
        System.out.println(Arrays.toString(num));
        System.out.println(Arrays.toString(low));
        for (int i = 0; i < size; i++) { 
   
            System.out.print("(" + lines[i][0] + "," + lines[i][1] + ")\t");
        }
        System.out.println();
    }

    public static void main(String[] args) { 
   
        SearchIntfFactory.produce(CutLine.class);
    }

}

今天的文章图的割点算法_割线和切线的区别「建议收藏」分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/68335.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注