110206 Erdös Numbers ( Erdos Numbers )


#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>

using namespace std;

#define ERDOS "Erdos, P."

struct AuthorInfo
{
public:
	AuthorInfo(const string& authorName) : m_Name(authorName), m_ErdosNo(-1)
	{
	}

	void SetErdosNo(int x)
	{
		m_ErdosNo = x;
	}

	int GetErdosNo()
	{
		return m_ErdosNo;
	}

	void AddPaper(int x)
	{
		m_Papers.insert(x);
	}

	const string& GetName()
	{
		return m_Name;
	}

	bool InvolvedInPaper(int paper)
	{
		return (m_Papers.find(paper) != m_Papers.end());
	}

	const set<int>& GetPapers()
	{
		return m_Papers;
	}

private:
	string m_Name;
	int m_ErdosNo;
	set<int> m_Papers;
};

class AuthorErdosResult
{
public:
	void AddResult(AuthorInfo* pAuthorInfo)
	{
		AddResult(pAuthorInfo->GetName(), pAuthorInfo->GetErdosNo());
	}

	int GetErdosNo(const string& authorName)
	{
		int nCnt = m_Result.count(authorName);
		if (nCnt > 0)
			return m_Result[authorName];
		return -1;
	}

private:
	void AddResult(const string& authorName, int erdosNo)
	{
		m_Result.insert(pair<string, int>(authorName, erdosNo));
	}

	map<string, int> m_Result;
};

class UnhandledAuthorCol
{
	typedef map<string, AuthorInfo*> AuthorsCol;

public:
	~UnhandledAuthorCol()
	{
		AuthorsCol::iterator iter = m_authors.begin();
		while(iter != m_authors.end())
		{
			delete iter->second;
			++iter;
		}
	}

	void AddAuthor(const string& authorName, int paper)
	{
		int cnt = m_authors.count(authorName);

		if (cnt <= 0)
			m_authors.insert(pair<string, AuthorInfo*>(authorName, new AuthorInfo(authorName)));
		m_authors[authorName]->AddPaper(paper);
	}

	void ExtractAuthorsAndSetErdosNo(int erdosNo, int paper, vector<AuthorInfo*>& extractedAuthors)
	{
		AuthorsCol::iterator iter = m_authors.begin();
		vector<string> toDeleteAuthors;
		while(iter != m_authors.end())
		{
			if (iter->second->InvolvedInPaper(paper))
			{
				iter->second->SetErdosNo(erdosNo);
				extractedAuthors.push_back(iter->second);
				toDeleteAuthors.push_back((iter->first));
			}
			++iter;
		}

		for (int i = 0; i < toDeleteAuthors.size(); ++i)
			m_authors.erase((toDeleteAuthors[i]));
	}

	AuthorInfo* ExtractAuthorsAndSetErdosNo(const string& name, int erdosNo)
	{
		AuthorsCol::iterator iter = m_authors.find(name);
		if (iter == m_authors.end())
			return NULL;

		AuthorInfo* pResult = iter->second;
		pResult->SetErdosNo(erdosNo);
		m_authors.erase(iter);
		return pResult;
	}

private:
	AuthorsCol m_authors;
};

class ErdosCalculator
{
public:
	void AddInfo(char* line, int paper)
	{
		int begin = 0;
		int end = 0;
		while(true)
		{
			if (line[end] == '.')
			{
				char next = line[end + 1];
				if (next == ':' || next == ',')
				{
					line[end + 1] = '\0';
					m_UnhandledAuthors.AddAuthor(string(line + begin), paper);

					if (next == ':')
					{
						return;
					}

					// else, then
					// next should be ',', and the next of next should be ' '.
					end += 3;
					begin = end;
					continue;
				}
			}
			else if (line[end] == ':') // There can be no '.' before the ':'.
			{
				line[end] = '\0';
				m_UnhandledAuthors.AddAuthor(string(line + begin), paper);
				return;
			}

			++end;
		}
	}

	void Calculate()
	{
		set<AuthorInfo*> handledAuthors;
		AuthorInfo* pErdosSelf = m_UnhandledAuthors.ExtractAuthorsAndSetErdosNo(string(ERDOS), 0);
		if (pErdosSelf == NULL)
		{
			pErdosSelf = new AuthorInfo(string(ERDOS));
			pErdosSelf->SetErdosNo(0);
		}

		handledAuthors.insert(pErdosSelf);
		vector<AuthorInfo*> addedAuthors;
		int erdosNo = 1;
		
		while(true)
		{
			set<AuthorInfo*>::iterator iter = handledAuthors.begin();
			while(iter != handledAuthors.end())
			{
				const set<int>& papers = (*iter)->GetPapers();
				set<int>::const_iterator const_iter = papers.begin();
				while(const_iter != papers.end())
				{
					m_UnhandledAuthors.ExtractAuthorsAndSetErdosNo(erdosNo, *const_iter, addedAuthors);
					++const_iter;
				}
				++iter;
			}

			ClearHandledAuthorInfos(handledAuthors);

			int nCnt = addedAuthors.size();
			if (nCnt <= 0)
				break;

			++erdosNo;
			for (int i = 0; i < nCnt; ++i)
				handledAuthors.insert(addedAuthors[i]);
			addedAuthors.clear();
		}
	}

	int GetErdosNo(char* pName)
	{
		return m_Result.GetErdosNo(string(pName));
	}

private:
	void ClearHandledAuthorInfos(set<AuthorInfo*>& authorInfos)
	{
		set<AuthorInfo*>::iterator iter = authorInfos.begin();
		while(iter != authorInfos.end())
		{
			m_Result.AddResult(*iter);
			delete (*iter);
			++iter;
		}
		authorInfos.clear();
	}
	
	UnhandledAuthorCol m_UnhandledAuthors;
	AuthorErdosResult m_Result;
};

#define MAX_CNT 4096

static void OutputAuthorErdosNo(char* name, int erdosNo)
{
	if (erdosNo < 0)
		cout << name << " infinity" << endl;
	else
		cout << name << " " << erdosNo << endl;
}

static void DoTestCase(int testCaseNo)
{
	int nPaperCnt, nAuthorCnt;

	cin >> nPaperCnt >> nAuthorCnt;
//	cin.ignore();
	char buf[MAX_CNT];
	fgets(buf, MAX_CNT, stdin); // Consume the '\n' after the author's count.

	ErdosCalculator calculator;
	for (int i = 0; i < nPaperCnt; ++i)
	{
		fgets(buf, MAX_CNT, stdin);
		calculator.AddInfo(buf, i);
	}

	calculator.Calculate();

	cout << "Scenario " << testCaseNo << endl;

	for (int i = 0; i < nAuthorCnt; ++i)
	{
		fgets(buf, MAX_CNT, stdin);
		int len = strlen(buf);
		if (buf[len - 1] == '\n')
			buf[len - 1] = '\0'; // Throw away the last '\n'.
		OutputAuthorErdosNo(buf, calculator.GetErdosNo(buf));
	}
}

static void DoTest()
{
	int nTestCaseCnt;
	cin >> nTestCaseCnt;
	for (int i = 1; i <= nTestCaseCnt; ++i)
	{
		DoTestCase(i);
	}
}

int main(int argc, char* argv[])
{
	DoTest();
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值