Bootstrap

【用deepseek和chatgpt做算法竞赛】——ChatGPT还是不行呀 -Minimum Cost Trees_4

往期

ChatGPT还是不行呀

0 评分规则

为了拿分咧,先来看看规则

0.1 评分等级
  • 单棵树: 如果是单棵树,得 5 分。
  • 满足延迟约束的单棵树: 如果树满足延迟约束,则得 10 分。
  • 两棵边不相交的树:如果是两棵边不相交的树,得 20 分。
  • 两棵边不相交且其中一棵满足延迟约束的树: 如果是两棵边不相交的树,并且其中一棵满足延迟约束,得40 分。
  • 两棵边不相交且都满足延迟约束的树: 如果是两棵边不相交的树,并且两棵都满足延迟约束,得 100 分。
0.2 评分算法

评分算法分为三个步骤:

  • 确定最高等级: 首先确定最高的等级 level,即最终提交的解满足的最大条件(如树的数量、延迟约束等)。
  • 计算基础分: 计算为达成该等级而获得的无条件分数 x。
  • 计算附加分: 根据一个公式来计算附加分。附加分的计算方式是:
    • b o n u s = 0.25 ∗ x ∗ ( 1 − s q r t ( 1 − ( b e s t S u m / p a r t i c i p a n t S u m ) ) ) bonus = 0.25 * x * (1 - sqrt(1 - (bestSum / participantSum))) bonus=0.25x(1sqrt(1(bestSum/participantSum)))
    • 其中 bestSum 是达成该等级的最小边成本(即最佳解的边成本之和),participantSum 是参与者提交的解的边成本之和。
0.3 解的要求

根据这些评分标准,参与者提交的解需要满足以下要求:

  • 图结构必须符合树的特性:即每一对节点之间必须只有一条路径(连通性要求),没有环路(无环性要求)。
  • 必须能够从根节点出发,并扩展到所有其他节点(唯一根节点的要求)。

根据这些要求让GPT给出程序,但是随着这个要求过多呀,就只能给出一个看着正确但实际有问题的成程序,如下

import sys
import heapq
from collections import defaultdict

def read_graph_from_stdin():
    """ 从标准输入读取图数据并解析 """
    lines = sys.stdin.read().strip().split("\n")

    n = int(lines[0].strip())  # 节点数
    s = int(lines[1].strip())  # 源点
    k = int(lines[2].strip())  # 目标节点数
    terminals = list(map(int, lines[3].strip().split()))  # 目标节点列表
    D = int(lines[4].strip())  # 延迟约束
    m = int(lines[5].strip())  # 边数

    graph = defaultdict(list)

    for i in range(6, 6 + m):
        a, b, c, d = map(int, lines[i].strip().split())
        graph[a].append((b, c, d))  # 存储 a -> b 的边
        graph[b].append((a, c, d))  # 存储 b -> a 的边(无向图)

    return n, s, terminals, D, graph


def is_cyclic(graph, n, visited, node, rec_stack):
    """ 判断图中是否存在环(深度优先遍历) """
    visited[node] = True
    rec_stack[node] = True

    for neighbor, _, _ in graph[node]:
        if not visited[neighbor]:
            if is_cyclic(graph, n, visited, neighbor, rec_stack):
                return True
        elif rec_stack[neighbor]:
            return True

    rec_stack[node] = False
    return False


def find_directed_tree(n, s, terminals, D, graph, avoid_edges=set()):
    """ 使用Dijkstra算法构建满足延迟约束的有向树,并尽量避免使用 avoid_edges """

    pq = [(0, s, -1)]  # (delay, node, parent)
    min_delay = {node: float('inf') for node in range(n)}
    min_delay[s] = 0
    tree_edges = []
    parent_map = {}
    
    while pq:
        delay, node, parent = heapq.heappop(pq)

        if parent != -1 and (parent, node) not in avoid_edges:
            tree_edges.append((parent, node))

        for neighbor, cost, edge_delay in sorted(graph[node], key=lambda x: x[2]):  # 按延迟排序
            if (node, neighbor) in avoid_edges:
                continue  # 避免使用第一棵树中的边

            new_delay = delay + edge_delay
            if new_delay <= D and new_delay < min_delay[neighbor]:
                min_delay[neighbor] = new_delay
                heapq.heappush(pq, (new_delay, neighbor, node))
                parent_map[neighbor] = node

    # 判断是否能够连接所有终端节点
    if not all(t in parent_map for t in terminals):
        return None  # 不能形成有效的树

    # 检查图是否包含环
    visited = [False] * n
    rec_stack = [False] * n
    for node in range(n):
        if not visited[node]:
            if is_cyclic(graph, n, visited, node, rec_stack):
                return None  # 如果存在环,返回无效树

    return tree_edges


def process_and_output():
    graph_data = read_graph_from_stdin()
    if not graph_data:
        return

    n, s, terminals, D, graph = graph_data

    # 找到第一棵树
    tree1_edges = find_directed_tree(n, s, terminals, D, graph)

    if not tree1_edges:
        print("无法找到符合要求的树")
        return

    used_edges = set(tree1_edges)

    # 尝试找到第二棵树(避免使用第一棵树的边)
    tree2_edges = find_directed_tree(n, s, terminals, D, graph, avoid_edges=used_edges)

    # 允许部分重用第一棵树的边
    if not tree2_edges:
        tree2_edges = find_directed_tree(n, s, terminals, D, graph, avoid_edges=set())

    if not tree2_edges:
        return

    print(2)  # 找到 2 棵树

    # 第一棵树
    print(len(tree1_edges))
    for a, b in tree1_edges:
        print(a, b)

    # 第二棵树
    print(len(tree2_edges))
    for a, b in tree2_edges:
        print(a, b)


if __name__ == "__main__":
    process_and_output()

我的感觉是以前找最小树的要求,只要能到就行,没有说要找两棵树这类型的开源程序,然后很多要求和评分,所以这个AI还是不能很好处理。因此,我决定更换策略,通过伪代码与AI交流,一步步来实现目标。

;