代码随想录算法训练营第56天|108. 冗余连接、109. 冗余连接II

1. 108. 冗余连接

题目链接:108. 冗余连接
文档讲解: 代码随想录

怎么判断边冗余。从前往后遍历每一条边,判断边的两个节点是否在同一个集合,如果不在,则将它们加入集合,如果在,说明这两个点已经连在一起了,则这条边冗余。

def find(u):
    if father[u] == u:
        return u 
    father[u] = find(father[u])
    return father[u]
def issame(u,v):
    u = find(u)
    v = find(v)
    return u == v 
#u <- v
def joinside(u,v):
    u = find(u)
    v = find(v)
    if u == v:
        return 
    else:
        father[v] = u 
n = int(input())
res = [0,0]
father = [0] * (n+1)
#初始化
for i in range(n+1):
    father[i] = i
for _ in range(n):
    s,t = map(int,input().split())
    if issame(s,t):
        #同根,则冗余
        res[0] = s
        res[1] = t 
    else:
        joinside(s,t)
print(f"{res[0]} {res[1]}")

2. 109. 冗余连接II

题目链接:109. 冗余连接II
文档讲解: 代码随想录

这道题和上一题的区别是,是有向图。本题的本质是,有一个有向图,是由一颗有向树+一条有向边组成的。有向树的性质,只有根节点入度为0,其他节点入度为1,因为该树除了根节点外的每个节点都有且只有一个父节点,而根节点没有父节点。有三种情况,第一种情况,找到入度为2的点,删哪条都一样,那么删掉一条指向该节点的边就行了。第二种情况,只能删特定的一条边,需要判断删除哪一条边后本图能够成为有向树。第三种情况,如果没有入度为2的点,说明图中有环,删除构成环的边就可以了。

#初始化father数组
def ini(father,n):
    for i in range(1,n+1):
        father[i] = i 
def find(u,father):
    if father[u] == u:
        return u 
    father[u] = find(father[u],father)
    return father[u]
def issame(u,v,father):
    u = find(u,father)
    v = find(v,father)
    return u == v
#u->v
def joinside(u,v,father):
    u = find(u,father)
    v = find(v,father)
    if u == v:
        return 
    father[u] = v 
#判断删掉一边后是否是树
def istree(father,n,nodes,delnode):
    ini(father,n)
    for i in range(n):
        if i == delnode:
            continue
        if issame(nodes[i][0],nodes[i][1],father):
            #有环,不是树
            return False
        joinside(nodes[i][0],nodes[i][1],father)
    return True 
#有环删掉
def getremove(father,n,nodes):
    ini(father,n)
    for i in range(n):
        if issame(nodes[i][0],nodes[i][1],father):
            print(f"{nodes[i][0]} {nodes[i][1]}")
            return 
        joinside(nodes[i][0],nodes[i][1],father)

def main():
    n = int(input())
    father = [0] * (n+1)
    nodes = []
    #统计入度
    indegree = [0] * (n+1)
    for _ in range(n):
        s,t = map(int,input().split())
        indegree[t] += 1 
        nodes.append((s,t)) 
    #找入度为2的点
    vec = []
    for i in range(n-1,-1,-1):
        if indegree[nodes[i][1]] == 2:
            vec.append(i)
    #情况一、二
    if len(vec) > 0:
        if istree(father,n,nodes,vec[0]):
            print(f"{nodes[vec[0]][0]} {nodes[vec[0]][1]}")
        else:
            print(f"{nodes[vec[1]][0]} {nodes[vec[1]][1]}")
        return 
    #1情况三
    getremove(father,n,nodes)
if __name__ == "__main__":
    main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值