题目描述
小航是计算机系的学生,但他并不喜欢自己的专业。在课余时间,小航喜欢研究社会学的内容,在他经过了多年的研究后,他发现了一个伟大的定理:世界上任意两个人之间最少需要k个友谊纽带就可以全部连接。他需要向世界公布这个研究成果,但是他还没有对这个定理进行验证,由于他急着陪女朋友,所以将验证这个定理的任务交给了他的朋友小杰和小坤。
由于人数太多,而导致任务量非常大,所以小杰和小坤找到了你,请你帮助他们验证这个结论。
输入描述:
第一行包含两个整数n和m,n为总共的人数,m为关系的对数。 接下来m行包含两个整数a和b,表示a和b是朋友关系。
输出描述:
如果n个人当中的某些人无法成为朋友,则输出-1。否则输出一个k,表示最少需要k个纽带就可以连接任意两个朋友(每两个人之间最多有一条纽带)。
示例1
5 4
1 2
2 3
3 4
4 5
输出
4
说明
1号朋友和5号朋友需要最多4个纽带才能连接
示例2
5 3
1 2
2 3
3 4
输出
-1
说明
1号朋友和5号朋友无法通过友谊纽带连接
备注
2≤n≤2∗10^3
0≤m≤2*10^3
1<=a,b<=n
代码
#include <bits/stdc++.h>
using namespace std;
const int Max = 2e3 + 10;
pair<int,int> p;
int f[Max];
int vis[Max];
vector<int> v[Max];
int maxl = 0;
int find(int a) {
return f[a] == a ? a : f[a] = find(f[a]);
}
void h(int a,int b) {
if (find(a) != find(b)) f[find(a)] = find(b);
}
int main() {
int n,m;
cin >> n >> m;
for (int i = 1;i <= n; i++)
f[i] = i;
for (int i = 1;i <= m; i++) {
int x, y;
scanf("%d%d", &x, &y);
v[x].push_back(y);
v[y].push_back(x);
h(x,y);
}
//并查集判断每个人关系是否连通
set<int> s;
for (int i = 1;i <= n; i++) {
s.insert(find(i));
if (s.size() == 2) {
cout << "-1";
return 0;
}
}
//遍历每个人的关系线,更新最长的一条线
for (int i = 1;i <= n;i++) {
memset(vis,0,sizeof(vis));
queue<pair<int, int> > q;
vis[i] = 1;
q.push({i,0});
while (!q.empty()) {
p = q.front();
q.pop();
int len = v[p.first].size();
for (int j = 0;j < len;j++) {
if (!vis[v[p.first][j]]) {
q.push({v[p.first][j],p.second + 1});
vis[v[p.first][j]] = 1;
maxl = max(maxl,p.second + 1);
}
}
}
}
cout << maxl;
return 0;
}