图论之多余的边(有向图)
题目描述
有一种有向树,该树只有一个根节点,所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节点都有且只有一个父节点,而根节点没有父节点。有向树拥有 n 个节点和 n - 1 条边。如图:
现在有一个有向图,有向图是在有向树中的两个没有直接链接的节点中间添加一条有向边。如图:
输入一个有向图,该图由一个有着 n 个节点(节点编号 从 1 到 n),n 条边,请返回一条可以删除的边,使得删除该条边之后该有向图可以被当作一颗有向树。
输入描述
第一行输入一个整数 N,表示有向图中节点和边的个数。
后续 N 行,每行输入两个整数 s 和 t,代表这是 s 节点连接并指向 t 节点的单向边
输出描述
输出一条可以删除的边,若有多条边可以删除,请输出标准输入中最后出现的一条边。
输入示例
3
1 2
1 3
2 3
输出示例
2 3
提示信息
在删除 2 3 后有向图可以变为一棵合法的有向树,所以输出 2 3
数据范围:
1 <= N <= 1000.
这道题和上一道的区别在于是有向的,由于总共有n条边和n个节点,要在n条边里找到让该图无法成为树的边。如果做了足够的图论题目,就能找出三种情况,第一种是没有成环,有入度为2的节点,随意删一条即可;第二种是成环且有入度为二的节点,则删除成环的那条边;第三种是成环但没有入度为2的节点,删除成环的那一条边
代码实现如下
`from collections import defaultdict
father=list()
def find(s):
if s==father[s]:
return
else:
father[s]=find(father[s])
return father[s]
def join(s,t):
root_s=father[s]
root_t=father[t]
if root_s==root_t:
return
else:
father[t]=root_s
def is_same(s,t):
root_s=find(s)
root_t=find(t)
if root_s==root_t:
return True
else:
return False
def is_tree_after_remove_edge(edges,edge,n):
global father
father=[i for i in range(n)]
for i in range(len(edges)):
if i==edge:
continue
s,t=edges[i]
if is_same(s,t):
return False
else:
join(s,t)
return True
def get_remove_edge(edges):
global father
father=[i for i in range(n)]
for i in range(len(edges)):
s,t=edges[i]
if is_same(s,t):
print(s,t)
return
else:
continue
if __name__=="__main__":
n=int(input())
edges=list()
in_degree=defaultdict(int)
for _ in range(n):
s,t=map(int,input().split())
edges.append([s,t])
in_degree[t]+=1
vec=list()
for i in range(n-1,-1,-1):
if in_degree[i]==2:
vec.append(i)
if len(vec)>0:
if is_tree_after_remove_edge(edges,vec[0],n):
print(edges[vec[0]][0],edges[vec[0]][1])
else:
print(edges[vec[1]][0],edges[vec[1]][1])
else:
get_remove_edge(edges)
`

浙公网安备 33010602011771号