【BFS】Friend Chains

HDU 4460 Friend Chains

Friend Chains

For a group of people, there is an idea that everyone is equals to or less than 6 steps away from any other person in the group, by way of introduction. So that a chain of “a friend of a friend” can be made to connect any 2 persons and it contains no more than 7 persons.
For example, if XXX is YYY’s friend and YYY is ZZZ’s friend, but XXX is not ZZZ’s friend, then there is a friend chain of length 2 between XXX and ZZZ. The length of a friend chain is one less than the number of persons in the chain.
Note that if XXX is YYY’s friend, then YYY is XXX’s friend. Give the group of people and the friend relationship between them. You want to know the minimum value k, which for any two persons in the group, there is a friend chain connecting them and the chain’s length is no more than k .
Input
There are multiple cases.
For each case, there is an integer N (2<= N <= 1000) which represents the number of people in the group.
Each of the next N lines contains a string which represents the name of one people. The string consists of alphabet letters and the length of it is no more than 10.
Then there is a number M (0<= M <= 10000) which represents the number of friend relationships in the group.
Each of the next M lines contains two names which are separated by a space ,and they are friends.
Input ends with N = 0.
Output
For each case, print the minimum value k in one line.
If the value of k is infinite, then print -1 instead.
Sample
Input

3
XXX
YYY
ZZZ
2
XXX YYY
YYY ZZZ
0

Output

2
题目大意
  • 给你 n n n 个人以及他们之间的朋友关系,找出最短的能够连接任意两个人的路径长度,没有就输出-1
  • 翻译一下,就是给你一个图,如果这个图是连通的,那么就求出这个图中任意两点最短距离的最大值,如果不连通,那么就输出-1
思路
  • 这里记录一种BFS做法
  • 首先,把输入的字符串映射成数字编号,成为我们喜欢的图的问题
  • 然后处理这个图即可,邻接表存图,以每一个结点为起始点,BFS搜索整个图,得出把这个图搜索完成之后得到的步数的最大值即可
  • 这样,时间复杂度就是 O ( n 2 ) O(n^2) O(n2) 的,题目数据为 1 0 3 10^3 103,够用了
  • 注意什么是“把图搜索完成了”:即,一次BFS,把所有的结点都遍历完一次
代码如下
#include <algorithm>
#include <climits>
#include <iostream>
#include <queue>
#include <string>
#include <unordered_map>
#include <vector>
using namespace std;

unordered_map<string, int> mp;//用于将字符串映射成数字编号
queue<pair<int, int> > q;//BFS队列,pair的一个值是结点编号,另一个是搜索步数
vector<vector<int> > dat;//邻接表
vector<bool> vis;//访问数组,常见于BFS和DFS
//下面是一些临时变量
string name, nm;
int n, m;
int i, max_val, cnt;
pair<int, int> top, tmp;

int bfs(int pstart) {
    while (!q.empty()) q.pop();
    q.push(make_pair(pstart, 0));
    vis[pstart] = true;
    cnt = 1;

    while (!q.empty()) {
        top = q.front();
        q.pop();
        for (int i = 0; i < dat[top.first].size(); i++) {
            if (vis[dat[top.first][i]]) continue;
            tmp = make_pair(dat[top.first][i], top.second + 1);
            cnt++;//数已经访问的结点个数
            if (cnt == n) return tmp.second;//如果已经访问完了,那么就返回此时的搜索步数
            q.push(tmp);
            vis[tmp.first] = true;
        }
    }
    return INT_MAX;//队列空了都没有“搜索完成”,说明是不连通图,返回一个很大的数
}

void solve() {
    while ((~scanf("%d", &n)) && n) {
        //对于每一组输入,都要清洗一遍容器
        dat.resize(n);
        for (i = 0; i < n; i++) dat[i].clear();
        vis.resize(n, false);
        mp.clear();
        max_val = 0;

        for (i = 0; i < n; i++) {
            cin >> name;
            mp[name] = i;
        }
        scanf("%d", &m);

        for (i = 0; i < m; i++) {
            cin >> name >> nm;
            //注意无向图要存两遍边
            dat[mp[name]].push_back(mp[nm]);
            dat[mp[nm]].push_back(mp[name]);
        }

        for (i = 0; i < n; i++) {
            fill(vis.begin(), vis.end(), false);
            max_val = max(max_val, bfs(i));//找出最长路径长度
            //这里可以预先判定bfs的结果是否等于INT_MAX,是的话就提前退出循环,避免不必要的运算,但是显得代码繁琐,这里没有使用
        }
        printf("%d\n", max_val == INT_MAX ? -1 : max_val);
    }
}

int main(void) {
    solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

渴望力量的猴子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值