图算法-割点

对于无向图,如果删除了一 个顶点,(顶点邻边也删除) 整个图连通分量数量变化,则这个顶点称为割点

 

 

 

# encoding = 'utf-8'

import sys
sys.path.append("..")
from sortedcontainers import SortedSet as TreeSet


class AdjSet:
    def __init__(self, filename):
        self._filename = filename
        lines = None
        with open(filename, 'r') as f:
            lines = f.readlines()
        if not lines:
            raise ValueError('Expected something from input file!')

        # lines[0] -> V E
        self._V, self._E = (int(i) for i in lines[0].split())

        if self._V < 0:
            raise ValueError('V must be non-negative')

        if self._E < 0:
            raise ValueError('E must be non-negative')

        # size V list of TreeSet
        self._adj = [TreeSet([]) for _ in range(self._V)]
        for each_line in lines[1:]:
            a, b = (int(i) for i in each_line.split())
            self.validate_vertex(a)
            self.validate_vertex(b)

            if a == b:
                raise ValueError('Self-Loop is detected!')

            if b in self._adj[a]:
                raise ValueError('Paralles edges are detected!')

            self._adj[a].add(b)
            self._adj[b].add(a)

    @property
    def V(self):
        return self._V

    @property
    def E(self):
        return self._E

    def has_edge(self, v, w):
        self.validate_vertex(v)
        self.validate_vertex(w)
        return w in self._adj[v]

    def adj(self, v):
        self.validate_vertex(v)
        return self._adj[v]

    def degree(self, v):
        return len(self.adj(v))

    def remove_edge(self, v, w):
        self.validate_vertex(v)
        self.validate_vertex(w)
        if w in self._adj[v]:
            self._adj[v].remove(w)
        if v in self._adj[w]:
            self._adj[w].remove(v)

    def validate_vertex(self, v):
        if v < 0 or v >= self._V:
            raise ValueError('vertex ' + str(v) + ' is invalid')

    def __str__(self):
        res = ['V = {}, E = {}'.format(self._V, self._E)]
        for v in range(self._V):
            res.append('{}: {}'.format(v, ' '.join(str(w) for w in self._adj[v])))
        return '\n'.join(res)

    def __repr__(self):
        return self.__str__()

    def __copy__(self):
        return AdjSet(self._filename)


class FindCutPoints:

    def __init__(self, G):
        self._G = G
        self._visited = [False] * G.V
        self._ord = [-1] * G.V
        self._low = [- 1] * G.V
        self._cnt = 0
        self._res = set()
        for v in range(G.V):
            if not self._visited[v]:
                self._dfs(v, v)

    def _dfs(self, v, parent):
        self._visited[v] = True
        self._ord[v] = self._cnt
        self._low[v] = self._ord[v]
        self._cnt += 1

        child = 0
        for w in self._G.adj(v):
            if not self._visited[w]:
                self._dfs(w, v)
                self._low[v] = min(self._low[v], self._low[w])
                if v != parent and self._low[w] >= self._ord[v]:
                    self._res.add(v)

                child += 1
                if v == parent and child > 1:
                    self._res.add(v)
            elif w != parent:
                self._low[v] = min(self._low[v], self._low[w])

    @property
    def result(self):
        return list(self._res)


if __name__ == '__main__':
    filename = 'g.txt'
    g = AdjSet(filename)
    find_cut_points = FindCutPoints(g)
    print(find_cut_points.result)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值