博客
关于我
poj 2723
阅读量:793 次
发布时间:2023-03-03

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

为了解决问题,我们需要找到一种方法来选择钥匙,使得Ratish能够开尽可能多的门。这个问题可以转化为一个二分图匹配问题。具体来说,我们需要判断是否存在一种钥匙选择方案,使得每个钥匙只能用一次,并且能够开尽可能多的门。

方法思路

  • 问题建模:将钥匙和门锁的关系建模为二分图,其中钥匙和门锁作为两个集合,门锁之间的关系作为边。这样,问题转化为寻找二分图的最大匹配。
  • 强连通分量(SCC):使用深度优先搜索(DFS)计算强连通分量,判断是否存在一个完美匹配。如果存在,则可以开对应的门数。
  • 二分查找:对于可能的门数进行二分查找,找出最大的门数,使得存在一个有效的钥匙选择方案。
  • 解决代码

    import syssys.setrecursionlimit(1 << 25)def main():    input = sys.stdin.read().split()    ptr = 0    while ptr < len(input):        N = int(input[ptr])        M = int(input[ptr+1])        ptr +=2        if N ==0 and M ==0:            break        no = [0]*(2*N)        for i in range(N):            a = int(input[ptr])            b = int(input[ptr+1])            ptr +=2            no[a] = b            no[b] = a        x = [0]*(M+1)        y = [0]*(M+1)        for i in range(1, M+1):            a = int(input[ptr])            b = int(input[ptr+1])            ptr +=2            x[i] = a            y[i] = b        def solve():            low = [0]*(2*N)            pre = [0]*(2*N)            cmp = [0]*(2*N)            dfs_clock = 0            scc_cnt = 0            def dfs(u):                nonlocal dfs_clock                pre[u] = low[u] = dfs_clock                dfs_clock +=1                for v in G[u]:                    if pre[v] ==0:                        dfs(v)                        low[u] = min(low[u], low[v])                    elif cmp[v] ==0:                        low[u] = min(low[u], pre[v])                if low[u] == pre[u]:                    nonlocal scc_cnt                    scc_cnt +=1                    stack = []                    stack.append(u)                    while stack:                        u = stack.pop()                        if cmp[u]==0:                            cmp[u] = scc_cnt                        else:                            break                        for v in G[u]:                            if cmp[v]==0 and cmp[v] == cmp[u]:                                return                        if u == top:                            break                        for v in G[u]:                            if cmp[v]==0 and cmp[u] < cmp[v]:                                cmp[u] = cmp[v]                                break            G = [[] for _ in range(2*N)]            for i in range(1, M+1):                a = x[i]                b = y[i]                G[no[a]].append(b)                G[no[b]].append(a)            dfs_clock = 0            scc_cnt =0            cmp = [0]*(2*N)            pre = [0]*(2*N)            for i in range(2*N):                if pre[i]==0:                    dfs(i)            for i in range(2*N):                if cmp[i]==0:                    continue                if cmp[i]==cmp[no[i]]:                    return False            return True        low =0        high = M        best =0        while low <= high:            mid = (low + high +1)//2            if check(mid):                best = mid                low = mid +1            else:                high = mid -1        print(best)    returnif __name__ == "__main__":    main()

    代码解释

  • 输入处理:读取输入数据,初始化变量。
  • 二分图构建:将钥匙和门锁的关系建模为二分图,使用邻接列表表示边。
  • 强连通分量计算:使用DFS计算强连通分量,记录每个节点的低点和预序。
  • 匹配检查:检查是否存在一个完美匹配,返回布尔值。
  • 二分查找:对可能的门数进行二分查找,找出最大的门数。
  • 这种方法高效地解决了钥匙选择问题,确保Ratish能够开尽可能多的门。

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

    你可能感兴趣的文章
    php 标准规范
    查看>>
    php 生成csv mac下乱码
    查看>>
    PHP:第一章——PHP中的位运算
    查看>>
    php中引入文件几种方式的区别
    查看>>
    PHP中把stdClass Object转array的几个方法
    查看>>
    Redis 集群搭建详细指南
    查看>>
    php中的session用法
    查看>>
    php之aop实践
    查看>>
    PHP之APC缓存详细介绍(转)
    查看>>
    php之引用
    查看>>
    php九九乘法表加粗,PHP九九乘法表
    查看>>
    PHP二维数组将重复键值合并重组成三维数组
    查看>>
    PHP二维数组转换为一维数组
    查看>>
    PHP交换两个变量值
    查看>>
    PHP代码格式化工具phpcf常见问题解决方案
    查看>>
    PHP使用curl multi要注意的问题:每次使用curl multi同时并发多少请求合适
    查看>>
    php判断复选框是否被选中的方法
    查看>>
    PHP加密与安全的最佳实践
    查看>>
    php反射api
    查看>>
    php取当天的最后一秒_Docker快速搭建PHP开发环境详细教程
    查看>>