友谊纽带(bfs+并查集)

友谊纽带

题目描述
小航是计算机系的学生,但他并不喜欢自己的专业。在课余时间,小航喜欢研究社会学的内容,在他经过了多年的研究后,他发现了一个伟大的定理:世界上任意两个人之间最少需要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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值