📜  门| GATE-CS-2003 |问题7(1)

📅  最后修改于: 2023-12-03 15:12:40.657000             🧑  作者: Mango

门 | GATE-CS-2003 |问题7

这道题目是从GATE-CS-2003中选出来的,主要考察的是对于离散数学的理解以及程序能力。

题干

一个图被称为有向完全图,如果每个节点都有一个从该节点到其他任何节点的有向边。在这个有向完全图中,每一个节点都被标记成0或者1。距离是从一个节点到另一个节点的路径上的不同标记数。在这个有向完全图中找到距离最小的两个节点。

输入

输入数据的第一行包含了测试用例的个数t。每个测试用例包含了两行,第一行是有向完全图的节点数n,第二行是n个0和1组成的序列。

输出

输出每一个测试用例中距离最小的两个节点的距离,如果有多个解,输出其中任意一个即可。

例子

输入:

2
4
0001
4
1001

输出:

1
1
解题思路

这个问题本质上是要求在一个完全有向图上求解两个点之间的最短距离,根据题目中的设定,距离是从一个节点到另一个节点的路径上的不同标记数,这个距离计算起来还比较简单。所以,我们可以尝试使用Floyd或者Dijkstra算法解决这个问题。

解法分析

Floyd算法

Floyd算法是一种动态规划的算法,它可以计算出任意两点之间的最短路径。为了方便,我们假设虚拟源节点之间的距离为0。其中,虚拟源节点是一个新的节点,我们可以将它与图中的所有节点连接起来,并且不需要额外的开销。具体的实现如下:

INF = 2**31 - 1

def floyd(graph, n):
    # 构建虚拟源节点
    for k in range(n + 1):
        for i in range(n + 1):
            for j in range(n + 1):
                graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j])
    return graph[1:][:]

Dijkstra算法

Dijkstra算法是解决最短路径问题的经典算法,基本思想是贪心算法,即每次找到目前距离起点最近的一个未标记节点,更新其周边的所有节点。实现如下:

INF = 2**31 - 1

def dijkstra(graph, n):
    dis = [INF for _ in range(n + 1)]
    dis[0] = 0
    vis = [False for _ in range(n + 1)]
    for i in range(n + 1):
        minDis = INF
        k = -1
        for j in range(n + 1):
            if dis[j] < minDis and not vis[j]:
                minDis = dis[j]
                k = j
        vis[k] = True
        for j in range(n + 1):
            dis[j] = min(dis[j], dis[k] + graph[k][j])
    return dis[1:]
代码实现
INF = 2**31 - 1

def floyd(graph, n):
    # 构建虚拟源节点
    for k in range(n + 1):
        for i in range(n + 1):
            for j in range(n + 1):
                graph[i][j] = min(graph[i][j], graph[i][k] + graph[k][j])
    return graph[1:][:]
    
def dijkstra(graph, n):
    dis = [INF for _ in range(n + 1)]
    dis[0] = 0
    vis = [False for _ in range(n + 1)]
    for i in range(n + 1):
        minDis = INF
        k = -1
        for j in range(n + 1):
            if dis[j] < minDis and not vis[j]:
                minDis = dis[j]
                k = j
        vis[k] = True
        for j in range(n + 1):
            dis[j] = min(dis[j], dis[k] + graph[k][j])
    return dis[1:]

if __name__ == '__main__':
    # 读取数据
    t = int(input())
    for _ in range(t):
        n = int(input())
        a = input()
        # 生成邻接矩阵
        graph = [[INF for _ in range(n + 1)] for _ in range(n + 1)]
        for i in range(n):
            for j in range(n):
                if i != j:
                    if a[i] != a[j]:
                        graph[i + 1][j + 1] = 1
                    else:
                        graph[i + 1][j + 1] = 0
        # 使用Floyd算法求解
        res = floyd(graph, n)
        ans = INF
        for i in range(n):
            for j in range(i + 1, n):
                ans = min(ans, res[i][j])
        print(ans)
总结

本题涉及到了离散数学中路径基础知识,比如最短路径等。本题的解法其实是比较直接的,使用Floyd或者Dijkstra算法即可,实现较为简单,可以适当做为日常练习。