算法提高 Degrees of Separation(map + Bfs)

试题 算法提高 Degrees of Separation

资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
  在我们联系日益紧密的世界里,人们推测每个人和其他人的分离度不超过六(六度分离)。在这个问题里,你需要写一个程序来找出人们的关系网络中最大的分离度。
  对于任意两个人,他们的分离度是联系两个人需要经过的最小的关系数。对于一个关系网络,最大的分离度是网络中任意两人的分离度的最大值。如果一个网络中有两个人没有通过关系链连接起来,这个网络是不连通的。
  如下图所示,一个网络可以用一些连接两个人的对称关系来描述。一条线段表示两个人之间有联系。网络A描述了一个分离度最大值为2的网络,网络B没有连通。在这里插入图片描述
输入格式
  输入包含多组描述关系网络的数据,对于每组数据,第一行有两个数P,表示网络中人的数目,和R,关系的对数。接下来一行是R个关系。每个关系用两个字符串表示,代表网络中有关系的两个人的名字。每个名字是不同的,并且中间没有空格。因为一个人可能和多个人有联系,一个名字可能在一组数据中出现多次。
  最后以一行两个0表示结束。
输出格式
  对于每个网络,输出网络中最大的分离度。如果这个网络是不连通的,输出DISCONNECTED。每一个网络输出后再输出一个回车。按照样例输出中的格式输出。
样例输入
4 4
Ashok Kiyoshi Ursala Chun Ursala Kiyoshi Kiyoshi Chun
4 2
Ashok Chun Ursala Kiyoshi
6 5
Bubba Cooter Ashok Kiyoshi Ursala Chun Ursala Kiyoshi Kiyoshi Chun
0 0
样例输出
Network 1: 2

Network 2: DISCONNECTED

Network 3: DISCONNECTED
数据规模和约定
  30%的数据2<=P<=15
  100%的数据2<=P<=50,R>=1

解题思路

这题考的是图论中两点之间的距离,只是这个边的权值都为1。有两个要点:
1.如何把字符串转换为结点
2.如何求最大分离度

解答1:利用STL中的map<string,int>,将一个字符串一一映射到int中。因为字符串会有重复,所以当一个字符串没有出现过的时候才给它分配一个int编号。之后,就可以用图论的方法解决了。
解答2:对每个结点进行Bfs,利用队列和dis[]数组(记录步数),这时会有两种情况:1 对一个结点bfs,没有访问完所有结点,显然这种情况图不连通,输出disconnected;2 一个结点成功Bfs所有结点,如果最"远"的一个结点的dis值比ans大,那么ans要更新。这样对所有结点Bfs完成以后,ans就是最大分离度了。
PS. 因为要用map,不得不用string,对于string类型的输入,强烈推荐使用Cin,而非scanf,因为编者在使用scanf对string输入的时候,出现了下面的情况,string在10的位置已经结束了,但是在11的位置竟然出现了字符a!!!不知道是为什么会这样,导致提交了好几次都未通过。
在这里插入图片描述
AC代码如下:

#include<stdio.h>
#include<iostream>
#include<queue>
#include<string>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;

const int MAXN = 50 + 1;
vector<int> graph[MAXN];	//邻接表
int P, R;
bool vis[MAXN];		//记录结点是否访问
int dis[MAXN];		//到达结点的步数
map<string, int> People;
int ans = 0;

void Bfs(int u) {		//标准的Bfs格式,因本题求最大分离度,略微复杂
	memset(dis, 0, sizeof(dis));
	memset(vis, 0, sizeof(vis));
	queue<int> Q;
	vis[u] = 1;
	Q.push(u);
	int num = 1;		//记录访问的结点个数

	while (!Q.empty()) {
		int now = Q.front();

		if (num == P && Q.size() == 1)	//判断结点是否都访问过了,并且是最后一个结点
			ans = max(ans, dis[now]);

		Q.pop();

		for (int i = 0; i < graph[now].size(); i++) {
			int next = graph[now][i];
			if (!vis[next]) {
				vis[next] = 1;
				dis[next] = dis[now] + 1;		//步数加1
				num++;			//已访问的结点加1
				Q.push(next);
			}
		}

	}
}

int main() {
	int ccase = 0;

	while (scanf("%d%d", &P, &R) && P&&R) {
		People.clear();
		for (int i = 0; i < MAXN; i++)
			graph[i].clear();
		ccase++;
		ans = 0;

		int k = 1;
		char c[20],d[20];
		//string c, d;
		for (int i = 0; i < R; i++) {
			//cin >> c >> d;
			scanf("%s%s",c,d);
			if(!People[c])		//将string映射到int
				People[c] = k++;
			if(!People[d])
				People[d] = k++;
			graph[People[c]].push_back(People[d]);
			graph[People[d]].push_back(People[c]);
		}

		for (int i = 1; i <= P; i++) {
			Bfs(i);
		}
		if (ans == 0)
			printf("Network %d: DISCONNECTED\n\n", ccase);
		else
			printf("Network %d: %d\n\n", ccase, ans);
	}
	return 0;
}
发布了17 篇原创文章 · 获赞 2 · 访问量 430

猜你喜欢

转载自blog.csdn.net/Raymond_YP/article/details/104417991