博客
关于我
POJ 2186:Popular Cows Tarjan模板题
阅读量:793 次
发布时间:2023-03-03

本文共 2336 字,大约阅读时间需要 7 分钟。

题目大意是给定一群牛,其中每头牛都会给其他牛点赞。点赞关系具有传递性,即如果A点赞了B,B点赞了C,那么A也会点赞C。我们需要找出被所有牛点赞的牛的数量。

分析过程

  • 建模为图问题:将牛看作图中的节点,点赞关系看作有向边。例如,A点赞B,则添加边A→B。
  • 传递闭包:由于点赞关系具有传递性,每个节点的可达节点集合形成一个传递闭包。我们需要找出在所有传递闭包下,能够被所有其他节点直接或间接到达的节点。
  • 强连通分量:使用Tarjan算法找出图中的强连通分量。每个强连通分量中的节点可以通过点赞关系相互到达。
  • 根节点判断:在每个强连通分量中,根节点是没有入边的节点。只有当所有节点都指向同一个根节点时,才能满足被所有牛点赞的条件。
  • 解决思路

    • 构建图结构:使用邻接表存储每个节点的出边。
    • Tarjan算法:计算每个节点的低点(low point)和深度优先序数(DFN)。通过比较DFN和低点来判断节点是否是根节点。
    • 统计根节点数量:如果只有一个根节点,则所有牛都指向它;否则,没有满足条件的牛。

    解决代码

    import sys
    sys.setrecursionlimit(1 << 25)
    def main():
    import sys
    input = sys.stdin.read
    data = input().split()
    idx = 0
    N = int(data[idx])
    idx += 1
    M = int(data[idx])
    idx +=1
    in_degree = [0]*(N+1)
    out_edges = [[] for _ in range(N+1)]
    for _ in range(M):
    A = int(data[idx])
    idx +=1
    B = int(data[idx])
    idx +=1
    out_edges[A].append(B)
    in_degree[B] +=1
    visited = [False]*(N+1)
    low = [0]*(N+1)
    dfn = [0]*(N+1)
    stack = []
    on_stack = [False]*(N+1)
    belong = [0]*(N+1)
    out = [0]*(N+1)
    Bcnt = 0
    Dindex = 0
    def tarjan(u):
    nonlocal Dindex
    dfn[u] = low[u] = Dindex
    Dindex +=1
    stack.append(u)
    on_stack[u] = True
    for v in out_edges[u]:
    if not visited[v]:
    visited[v] = True
    tarjan(v)
    low[u] = min(low[u], low[v])
    elif on_stack[v]:
    low[u] = min(low[u], dfn[v])
    if dfn[u] == low[u]:
    Bcnt +=1
    while True:
    w = stack.pop()
    on_stack[w] = False
    belong[w] = Bcnt
    if w == u:
    break
    for u in range(1, N+1):
    if not visited[u]:
    tarjan(u)
    for u in range(1, N+1):
    for v in out_edges[u]:
    if belong[u] != belong[v]:
    out[belong[u]] +=1
    root_count = 0
    root = 0
    for u in range(1, Bcnt+1):
    if out[u] == 0:
    root_count +=1
    root = u
    if root_count == 1:
    print(root)
    else:
    print(0)
    if __name__ == "__main__":
    main()

    代码解释

  • 输入处理:读取输入数据,构建节点之间的出边列表和入度数组。
  • Tarjan算法:进行深度优先搜索,计算每个节点的低点和DFN,并标记节点是否是根节点。
  • 传递闭包处理:更新每个节点的出度,统计每个传递闭包中的出度。
  • 根节点统计:找出所有出度为0的节点,统计其数量。如果只有一个,则输出该节点;否则输出0。
  • 该方法通过Tarjan算法高效地处理了大规模图数据,确保了算法的正确性和性能。

    转载地址:http://yyxfk.baihongyu.com/

    你可能感兴趣的文章
    PHP:第一章——PHP中的位运算
    查看>>
    Redis五种核心数据结构的基本使用与应用场景
    查看>>
    phprpc简单使用
    查看>>
    php中引入文件几种方式的区别
    查看>>
    PHP中把stdClass Object转array的几个方法
    查看>>
    PHP中有关正则表达式的函数集锦
    查看>>
    Redis 集群搭建详细指南
    查看>>
    php中的session用法
    查看>>
    Redis 限速器及问题
    查看>>
    php中高级基础知识点
    查看>>
    php中,如何将编译后的代码,反编译回去。
    查看>>
    php之aop实践
    查看>>
    PHP之APC缓存详细介绍(转)
    查看>>
    php之memcache,memcached
    查看>>
    php之引用
    查看>>
    PHP之数组和函数的基本教程
    查看>>
    php九九乘法表加粗,PHP九九乘法表
    查看>>
    PHP二维数组将重复键值合并重组成三维数组
    查看>>
    PHP二维数组转换为一维数组
    查看>>
    PHP交换两个变量值
    查看>>