Algorithm 感染者发现算法

Algorithm 感染者发现算法,algorithm,optimization,Algorithm,Optimization,我有一个算法,可以在给定的输入中解决“受影响的人”。 我必须解决受影响人员的名单。人是用数字来表示的,两个人在给定的时间N相互作用。如果一个人受到影响,另一个人也会受到影响 首先,给出了N(人数)和M(总互动次数)。 然后在M行中给出(P1-P2时间) 比如说,, 5.5 2 3 1 1 2 2 3 4 2 13 2 5 4 是的 这意味着有5个人,他们有5次互动,后面有5行表示第1次第2人和第3人会面,第2次第1人和第2人会面,第2次第3人和第4人会面,依此类推。(时间可能不按顺序排列) 一开

我有一个算法,可以在给定的输入中解决“受影响的人”。 我必须解决受影响人员的名单。人是用数字来表示的,两个人在给定的时间N相互作用。如果一个人受到影响,另一个人也会受到影响

首先,给出了N(人数)和M(总互动次数)。 然后在M行中给出(P1-P2时间)

比如说,, 5.5

2 3 1

1 2 2

3 4 2

13

2 5 4

是的

这意味着有5个人,他们有5次互动,后面有5行表示第1次第2人和第3人会面,第2次第1人和第2人会面,第2次第3人和第4人会面,依此类推。(时间可能不按顺序排列)

一开始,人1总是被感染。

所以在时间2,人1和人2相遇,使人2被感染, 第1人和第3人在第3时间相遇,使第3人受到感染, 最后,第二个人和第五个人在第四时间相遇,使第五个人受到感染

这使得人在最后感染了1,2,3,5

互动是随时间而发生的,多个互动可以同时发生,如果是这样的话,大多数人都必须考虑 受影响

例如,如果第1人和第3人被感染,并且(4 6 3)(3 6 3)作为输入,则必须首先计算(3 6 3)以使第6人被感染,第4人也被感染

为了解决这个问题,我创建了这个算法,它的运行时间非常糟糕,我需要帮助优化这个算法

inputs = input()
peopleNum = int(inputs.split()[0])
times = int(inputs.split()[1])
peopleMeet = {}
affectedPeople = [1]
for i in range(times):
    occur = input()
    person1 = int(occur.split()[0])
    person2 = int(occur.split()[1])
    time = int(occur.split()[2])
    if not time in peopleMeet:
        peopleMeet[time] = [(person1, person2)]
    else:
        for occur in range(len(peopleMeet[time])):
            if set(peopleMeet[time][occur]) & set((person1,person2)):
                peopleMeet[time][occur] = peopleMeet[time][occur] + ((person1,person2,))
                break
            if occur == (len(peopleMeet[time]) - 1):
                peopleMeet[time].append((person1,person2))
for time in sorted(peopleMeet):
    for occur in peopleMeet[time]:
        if set(affectedPeople) & set(occur):
            affectedPeople.extend(list(occur))
print(' '.join([str(x) for x in set(affectedPeople)]))
我对stack overflow非常陌生,我不习惯格式和发布指南,所以如果我错了,我很抱歉。并提前感谢您。

伪代码:

affectedPeople = bool array of size N + 1, initialized at false
affectedPeople[1] = True
sort the interactions based on time
iterate interactions and group them by time
for each group x:
    create a graph with interactions from that group as edges
    do a dfs on each affectedPeople present on these interactions. All the reached nodes will be affected
    add these nodes to affectedPeople (set them to True)
count amount of i with affectedPeople[i] = True
请参见代码中的注释:

DATA = [[2, 3, 1], [1, 2, 2], [3, 4, 2], [1, 3, 3], [2, 5, 4]]

# status contains the contamination status for each people in the dataset
# At the begining we will have only [1] contaminated so: 
# {1: True, 2: False, 3: False, 4: False, 5: False}
people_status = {}
for people_id in set(x[0] for x in DATA).union(x[1] for x in DATA):
    people_status[people_id] = people_id == 1

# meeting contains DATA grouped by time so with this dataset we will have:
# {1: [[2, 3]], 2: [[1, 2], [3, 4]], 3: [[1, 3]], 4: [[2, 5]]}
meeting = {}
for x in DATA:
    if x[2] in meeting:
        meeting[x[2]].append(x[:2])
    else:
        meeting[x[2]] = [x[:2]]


# now we just have to update people_status while time evolve
for time in sorted(meeting.keys()):
    while True:
        status_changed = False
        for couple in meeting[time]:
            if people_status[couple[0]] != people_status[couple[1]]:
                status_changed = True
                people_status[couple[0]] = people_status[couple[1]] = True
        if not status_changed:
            break

# create the list of infected people
infected_people = []
for people_id, status in people_status.items():
    if status:
        infected_people.append(people_id)


print(infected_people)
将打印结果:

[1, 2, 3, 5]

解决这个问题的另一种方法是使用
union-find
算法,该算法的运行时复杂性为
O(n*log(n))
。这个想法非常直截了当:

  • 根据时间参数按升序对给定输入进行排序

  • 按时间对交互进行分组,对于每个组,迭代交互并将参与相同交互的人员联合起来

  • 在联合操作中,如果组被感染,则保留信息(请参阅代码以获得更好的理解)

  • 对于该组中参与互动的每个人,检查他是否属于感染组,并将其标记为已感染

  • 将此组中涉及的人员的联合查找状态重置为原始状态,以便我们可以继续重新处理其他组,同时保留有关当前受感染人员的信息

下面是相同的代码:

MAX_N = 1000

parent = list(range(MAX_N))
infected = [False] * MAX_N

def find(x):
    if x == parent[x]: return x
    parent[x] = find(parent[x])
    return parent[x]

def union(x, y):
    parent_x = find(x)
    parent_y = find(y)

    # If either of the two clusters we're joining is infected
    # Infect the combined cluster as well
    infected[parent_y] = infected[parent_x] or infected[parent_y]
    parent[parent_x] = parent_y

def solve(inputs):
    infected[1] = True
    # Sort the input by the time parameter
    inputs.sort(key=lambda x: x[2])
    answer_set = set()

    i = 0
    while i < len(inputs):
        persons = set()
        cur_time =  inputs[i][2]

        # Iterate over interactions belonging to the same group i.e. same time
        while i < len(inputs) and inputs[i][2] == cur_time:
            person_x = inputs[i][0]
            person_y = inputs[i][1]

            persons.add(person_x)
            persons.add(person_y)

            # Union the people involed in the interaction
            union(person_x, person_y)
            i += 1

        for person in persons:
            group = find(person)
            # If the person belongs to an infected group, he's infected as well
            if infected[group]: 
                infected[person] = True
                answer_set.add(person)

        # Reset the union-find state as we move to the next time step
        for person in persons:
            parent[person] = person

    return answer_set

print (solve([[2, 3, 1], [1, 2, 2], [1, 3, 3], [2, 5, 4], [3, 4, 2]]))
MAX\u N=1000
父项=列表(范围(最大值))
已感染=[错误]*最大值
def查找(x):
如果x==父项[x]:返回x
父[x]=查找(父[x])
返回父项[x]
def接头(x,y):
父项_x=查找(x)
父项_y=查找(y)
#如果我们要加入的两个集群中的任何一个被感染
#也感染组合集群
受感染的[父母的y]=受感染的[父母的x]或受感染的[父母的y]
父项[父项x]=父项y
def solve(输入):
已感染[1]=真
#按时间参数对输入进行排序
inputs.sort(key=lambda x:x[2])
答案(set=set)
i=0
而i
我脑子里有一个算法,但在此之前我需要了解一些事情,在1 3 1和2 3 1的情况下会发生什么情况,在这种情况下,1人和3人在时间1相遇,2人和3人在时间1相遇,这三个人都会被感染吗?或者像这样的场景不会发生,因为在同一时间你只能遇到一个person@zenwraight下面的例子说明,在这些情况下,大多数人必须被视为受到影响。