Erdős数字描述了一个人与数学家PaulErdős之间的“协作距离”,以数学论文的作者身份衡量。要分配一个Erdős号码,某人必须是另一个具有有限Erdős号码的人的研究论文的共同作者。 PaulErdős的Erdős数为零。任何其他人的Erdős数字是k + 1,其中k是任何共同作者的最低Erdős数。 Wikipedia。
鉴于作者(和论文)的列表,我想为一组作者制作一个Erdős编号。源数据如下(来自输入.txt文件):
1(means only one scenario from this input, could have more than one from other entries)
4 3
Smith, M.N., Martin, G., Erdos, P.: Newtonian forms of prime factors
Erdos, P., Reisig, W.: Stuttering in petri nets
Smith, M.N., Chen, X.: First order derivates in structured programming
Jablonski, T., Hsueh, Z.: Selfstabilizing data structures
Smith, M.N.
Hsueh, Z.
Chen, X.
计算Erdős数字的作者是:
Smith, M.N.
Hsueh, Z.
Chen, X.
我目前的计划是从每个条目中取出名称,并形成名称的列表(或列表列表)。但我不确定最好的方法。我该怎么用? numpy的?的ReadLine?
更新: 输出应如下所示:
Scenario 1
Smith, M.N. 1
Hsueh, Z. infinity
Chen, X. 2
答案 0 :(得分:2)
为了更好地理解这个问题,请注意,这只是unweighted single-source shortest path problem,可以使用Breadth-first Search来解决。 您问题中的图表定义为:
对于您的示例,图表如下:
Reisig | | Erdos -- Martin | / | / | / | / | / Smith -- Chen Jablonski -- Hsueh
因此算法最初会将距离0指定为Erdos,将无穷大指定给其他人。然后,当它迭代地访问邻居时,它指定增加的距离。因此,下一次迭代会将距离(或在本例中为鄂尔多斯数)1分配给Reisig,Martin和Smith。下一次和最后一次迭代将为Chen分配2的距离。 Jablonski和Hsueh的距离将保留为无限远。
使用Adjacency List的图表表示:
e = Erdos r = Reisig m = Martin s = Smith c = Chen j = Jablonski h = Hsueh e: r m s r: e m: e s s: e c c: s j: h h: j
使用Python解决它的代码:
import Queue
def calc_erdos(adj_lst):
erdos_numbers = {}
queue = Queue.Queue()
queue.put(('Erdos, P.', 0))
while not queue.empty():
(cur_author, dist) = queue.get()
if cur_author not in erdos_numbers:
erdos_numbers[cur_author] = dist
for author in adj_lst[cur_author]:
if author not in erdos_numbers:
queue.put((author, dist+1))
return erdos_numbers
def main():
num_scenario = int(raw_input())
raw_input() # Read blank line
for idx_scenario in range(1, num_scenario+1):
[num_papers, num_queries] = [int(num) for num in raw_input().split()]
adj_lst = {}
for _ in range(num_papers):
paper = raw_input()
[authors, title] = paper.split(':')
authors = [author.strip() for author in authors.split(',')]
authors = [', '.join(first_last) for first_last in zip(authors[::2], authors[1::2])]
# Build the adjacency list
for author in authors:
author_neighbors = adj_lst.get(author,set())
for coauthor in authors:
if coauthor == author:
continue
author_neighbors.add(coauthor)
adj_lst[author] = author_neighbors
erdos_numbers = calc_erdos(adj_lst)
print 'Scenario %d' % idx_scenario
for _ in range(num_queries):
author = raw_input()
print '%s %s' % (author, erdos_numbers.get(author,'infinity'))
if __name__=='__main__':
main()
与输入:
1 4 3 Smith, M.N., Martin, G., Erdos, P.: Newtonian forms of prime factors Erdos, P., Reisig, W.: Stuttering in petri nets Smith, M.N., Chen, X.: First order derivates in structured programming Jablonski, T., Hsueh, Z.: Selfstabilizing data structures Smith, M.N. Hsueh, Z. Chen, X.
将输出:
Scenario 1 Smith, M.N. 1 Hsueh, Z. infinity Chen, X. 2
注意:
更普遍的问题可以描述为single-source shortest path problem,最简单的解决方案是使用Djikstra's Algorithm。
答案 1 :(得分:0)
我已经提交了一个问题的编辑,试图澄清你希望实现的目标。基于此,我编写了以下代码来回答您想要问的想法:
f = ['Smith, M.N., Martin, G., Erdos, P.: Newtonian forms of prime factors',
'Erdos, P., Reisig, W.: Stuttering in petri nets',
'Smith, M.N., Chen, X.: First order derivates in structured programming',
'Jablonski, T., Hsueh, Z.: Selfstabilizing data structures']
author_en = {} # Dict to hold scores/author
coauthors = []
targets = ['Smith, M.N.','Hsueh, Z.','Chen, X.']
for line in f:
# Split the line on the :
authortext,papers = line.split(':')
# Split on comma, then rejoin author (every 2)
# See: http://stackoverflow.com/questions/9366650/string-splitting-after-every-other-comma-in-string-in-python
authors = authortext.split(', ')
authors = map(', '.join, zip(authors[::2], authors[1::2]))
# Authors now contains a list of authors names
coauthors.append( authors )
for author in authors:
author_en[ author ] = None
author_en['Erdos, P.'] = 0 # Special case
此时我们现在有一个列表列表:每个列表包含来自给定出版物的共同作者和用于保存分数的词典。我们需要迭代每篇论文并为作者分配一个分数。我对鄂尔多斯得分的计算并不完全清楚,但你可能想要将得分分配循环直到没有变化 - 以便考虑以后影响早期得分的论文。
for ca in coauthors:
minima = None
for a in ca:
if author_en[a] != None and ( author_en[a]<minima or minima is None ): # We have a score
minima = author_en[a]
if minima != None:
for a in ca:
if author_en[a] == None:
author_en[a] = minima+1 # Lowest score of co-authors + 1
for author in targets:
print "%s: %s" % ( author, author_en[author] )
答案 2 :(得分:0)
万一有人在寻找Java实现:
import java.util.*;
public class P10044 {
public static void main(String[] args) {
Scanner c = new Scanner(System.in);
int cases = c.nextInt();
for (int currentCase = 1; currentCase<=cases; currentCase++) {
int p = c.nextInt();
int n = c.nextInt();
c.nextLine();
HashMap<String, ArrayList<String>> graph = new HashMap<>();
String[] testingNames = new String[n];
ArrayList<String> authors = new ArrayList<>();
HashMap<String, Integer> eNums = new HashMap<>();
while (p-- > 0) {
String[] paperAuthors = c.nextLine().split(":")[0].split("\\.,");
for (int i = 0; i < paperAuthors.length; i++) {
if (paperAuthors[i].charAt(paperAuthors[i].length() - 1) != '.')
paperAuthors[i] += '.';
paperAuthors[i] = paperAuthors[i].trim();
}
for (String author : paperAuthors)
if (!authors.contains(author))
authors.add(author);
// create and update the graph
for (String name : paperAuthors) {
ArrayList<String> updatedValue;
if (graph.keySet().contains(name))
updatedValue = graph.get(name);
else
updatedValue = new ArrayList<>();
for (String paperAuthor : paperAuthors)
if (!paperAuthor.equals(name))
updatedValue.add(paperAuthor);
graph.put(name, updatedValue);
}
}
//initialize the eNums map:
for (String author : authors)
if (!author.equals("Erdos, P."))
eNums.put(author, Integer.MAX_VALUE);
else
eNums.put(author, 0);
for (int i = 0; i < n; i++)
testingNames[i] = c.nextLine();
calculateEnums("Erdos, P.", graph, eNums);
System.out.println("Scenario " + currentCase);
for (String name : testingNames)
if (!eNums.keySet().contains(name) || eNums.get(name) == Integer.MAX_VALUE)
System.out.println(name + " infinity");
else
System.out.println(name + " " + eNums.get(name));
}
}
private static void calculateEnums(String name, HashMap<String, ArrayList<String>> graph,
HashMap<String, Integer> eNums) {
ArrayList<String> notCalculated = new ArrayList<>();
notCalculated.add(name);
while (notCalculated.size() > 0) {
String currentName = notCalculated.get(0);
for (String connectedName : graph.get(currentName)) {
if (eNums.get(connectedName) > eNums.get(currentName)) {
eNums.put(connectedName, eNums.get(currentName) + 1);
if(!notCalculated.contains(connectedName))
notCalculated.add(connectedName);
}
}
notCalculated.remove(0);
}
// recursive implementation but will result in TLE
// for(String connected: graph.get(name)) {
// if (eNums.get(connected) > eNums.get(name)) {
// eNums.put(connected, eNums.get(name) + 1);
// calculateEnums(connected, graph, eNums);
// }
// }
}
}