蓝桥杯算法提高 Degrees of Separation (并查集&Floyd)

                                 算法提高 Degrees of Separation  

问题描述

  在我们联系日益紧密的世界里,人们推测每个人和其他人的分离度不超过六(六度分离)。在这个问题里,你需要写一个程序来找出人们的关系网络中最大的分离度。
  对于任意两个人,他们的分离度是联系两个人需要经过的最小的关系数。对于一个关系网络,最大的分离度是网络中任意两人的分离度的最大值。如果一个网络中有两个人没有通过关系链连接起来,这个网络是不连通的。
  如下图所示,一个网络可以用一些连接两个人的对称关系来描述。一条线段表示两个人之间有联系。网络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

 并查集判断是否构成连通图,Flody算法求网络中最大的分离度(即所有两点之间最短距离中的最大值)

AC Code: 

#include <iostream>
#include <cstring>
#include <queue>
#include <stack>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <vector>
#include <algorithm>
#include <map>
#include <set>
#define Mod 1000000007
#define INF 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define eps 1e-8
#define lowbit(x) (x&-x);
typedef long long ll;
using namespace std;
static const int MAX_N = 1e5 + 5;
const double pi = acos(-1);
int dis[55][55];	//两点间距离
int pre[55];	//并查集前驱
void init() {
	for (int i = 1; i < 55; i++) {
		pre[i] = i;
		for (int j = 1; j < 55; j++) {
			dis[i][j] = (i == j ? 0 : INF);
		}
	}
}
int Find(int x) {
	if (pre[x] != x) {
		pre[x] = Find(pre[x]);
	}
	return pre[x];
}
void Union(int x, int y) {
	int fx = Find(x), fy = Find(y);
	if (fx != fy) {
		pre[fx] = fy;
	}
}
int main(){
	int P, R;
	int cas = 0;
	while (scanf("%d%d", &P, &R) != EOF) {
		if (P == 0 && R == 0) break;
		init();
		map<string, int>mps;	//标记英文名
		int cnt = 0;		//编号
		for (int i = 0; i < R; i++) {
			string s1, s2;
			cin >> s1 >> s2;
			if (!mps[s1]) {
				mps[s1] = ++cnt;
			}
			if (!mps[s2]) {
				mps[s2] = ++cnt;
			}
			Union(mps[s1], mps[s2]);//合并
			dis[mps[s1]][mps[s2]] = dis[mps[s2]][mps[s1]] = 1;
		}
		/*floyd算法*/
		for (int k = 1; k <= P; k++) {
			for (int i = 1; i <= P; i++) {
				for (int j = 1; j <= P; j++) {
					dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
				}
			}
		}
		int sum = 0;
		/*是否构成连通图*/
		for (int i = 1; i <= P; i++) {	
			if (pre[i] == i) {
				sum++;
			}
		}
		if (sum == 1) {
			int maxl = -INF;
			/*连通图中任意两点最短距离中的最大值*/
			for (int i = 1; i <= P; i++) {
				for (int j = 1; j <= P; j++) {
					if (dis[i][j] < INF) {
						maxl = max(dis[i][j], maxl);
					}
				}
			}
			printf("Network %d: %d\n", ++cas, maxl);
		}
		else {
			printf("Network %d: DISCONNECTED\n", ++cas);
		}
		putchar('\n');
	}
	return 0;
}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值