2

In any group of people there are many pairs of friends. Assume that two people who share a friend are friends themselves. (Yes, this is an unrealistic assumption in real life, but let's make it nevertheless). In other words, if people A and B are friends and B is friends with C, then A and C must also be friends. Using this rule we can partition any group of people into friendship circles as long as we know something about the friendships in the group.

Write a function networks() that takes two parameters. The first parameter is the number of people in the group and the second parameter is a list of tuple objects that define friends. Assume that people are identified by numbers 0 through n-1. For example, tuple (0, 2) says that person 0 is friends with person 2. The function should print the partition of people into friendship circles. The following shows several sample runs of the function:

>>>networks(5,[(0,1),(1,2),(3,4)])#execute

Social network 0 is {0,1,2}

Social Network 1 is {3,4}

I am honestly pretty lost on how to start this program, any tips would be greatly appreciated.

4

3 に答える 3

1
def networks(n,lst):
groups= []
for i in range(n)
    groups.append({i})
for pair in lst:
    union = groups[pair[0]]|groups[pair[1]]
    for p in union:
        groups[p]=union
sets= set()
for g in groups:
    sets.add(tuple(g))
i=0
for s in sets:
    print("network",i,"is",set(s))
    i+=1

これは、誰かが気にかけているなら私が探していたものです。

于 2013-03-21T15:53:05.723 に答える
1

これを解決するために使用できる効率的なデータ構造の 1 つdisjoint setに、構造体とも呼ばれる がありunion-findます。しばらく前に、私は別の回答のために1つを書きました。

構造は次のとおりです。

class UnionFind:
    def __init__(self):
        self.rank = {}
        self.parent = {}

    def find(self, element):
        if element not in self.parent: # leader elements are not in `parent` dict
            return element
        leader = self.find(self.parent[element]) # search recursively
        self.parent[element] = leader # compress path by saving leader as parent
        return leader

    def union(self, leader1, leader2):
        rank1 = self.rank.get(leader1,1)
        rank2 = self.rank.get(leader2,1)

        if rank1 > rank2: # union by rank
            self.parent[leader2] = leader1
        elif rank2 > rank1:
            self.parent[leader1] = leader2
        else: # ranks are equal
            self.parent[leader2] = leader1 # favor leader1 arbitrarily
            self.rank[leader1] = rank1+1 # increment rank

これを使用して問題を解決する方法は次のとおりです。

def networks(num_people, friends):
    # first process the "friends" list to build disjoint sets
    network = UnionFind()
    for a, b in friends:
        network.union(network.find(a), network.find(b))

    # now assemble the groups (indexed by an arbitrarily chosen leader)
    groups = defaultdict(list)
    for person in range(num_people):
        groups[network.find(person)].append(person)

    # now print out the groups (you can call `set` on `g` if you want brackets)
    for i, g in enumerate(groups.values()):
        print("Social network {} is {}".format(i, g))
于 2013-03-11T06:44:30.910 に答える
0

グラフ内の連結要素に基づくソリューションを次に示します( @Blckknghtによって提案されています)。

def make_friends_graph(people, friends):
    # graph of friends (adjacency lists representation)
    G = {person: [] for person in people} # person -> direct friends list
    for a, b in friends:
        G[a].append(b) # a is friends with b
        G[b].append(a) # b is friends with a
    return G

def networks(num_people, friends):
    direct_friends = make_friends_graph(range(num_people), friends)
    seen = set() # already seen people

    # person's friendship circle is a person themselves 
    # plus friendship circles of all their direct friends
    # minus already seen people
    def friendship_circle(person): # connected component
        seen.add(person)
        yield person

        for friend in direct_friends[person]:
            if friend not in seen:
                yield from friendship_circle(friend)
                # on Python <3.3
                # for indirect_friend in friendship_circle(friend):
                #     yield indirect_friend

    # group people into friendship circles
    circles = (friendship_circle(person) for person in range(num_people)
               if person not in seen)

    # print friendship circles
    for i, circle in enumerate(circles):
        print("Social network %d is {%s}" % (i, ",".join(map(str, circle))))

例:

networks(5, [(0,1),(1,2),(3,4)])
# -> Social network 0 is {0,1,2}
# -> Social network 1 is {3,4}
于 2013-03-12T04:36:48.247 に答える