这道题 作为刷题第三天的结尾题 有一点难度,有很多我学过但是忘记的知识~,正好温习一下,先放个代码吧,最后总结一下:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
/*
题目大意:
有n个人,m个关系,A认识B经过最少的人数为A到B的关系长度,问在这n个人中,任意两个人相互认识的最长关系长度为多少。如果有两个人无法通过关系认识则输出-1。
本题的关键在于bfs
我们需要得知每两个节点的最短距离
我们可以利用bfs获得每个节点到其他节点的最短距离 取最大值 重复n次 如果认识不了距离为-1
最后的最大距离就是所谓的k
*/
//找哪个点的最小值 一共多少个点
const int INF = 1e9;
vector<int> bfs(int start,const vector<vector<int>>& adj,int n){
vector<int> distance(n, INF);//初始化最短距离数组
queue<int> q;
q.push(start);
distance[start] = 0;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v : adj[u]) {
if (distance[v] == INF) {
distance[v] = distance[u] + 1;
q.push(v);
}
}
}
return distance;
}
int main() {
int n;
while (cin >> n && n != 0)
{
//实现名字和索引之间的对应关系 便于插入邻接表
map<string, int> name_to_index;
vector<string> index_to_name(n);
for (int i = 0; i < n; i++) {
string name;
cin >> name;
name_to_index[name] = i;
index_to_name[i] = name;
}
int M;
cin >> M;
vector<vector<int>> adj(n);
//建立无向图的邻接表 高纬度为n代表n个节点 低维度代表节点所联系的节点向量
for (int i = 0; i < M; i++) {
string name1;
string name2;
cin >> name1 >> name2;
int u=name_to_index[name1];
int v=name_to_index[name2];
//由于朋友是双向的 所以节点都要添加
adj[u].push_back(v);
adj[v].push_back(u);
}
int result = 0;
bool is_connected = true;
for (int i = 0; i < n; ++i) {
vector<int> distance = bfs(i, adj, n);
int max_distance = 0;
for (int j = 0; j < n; ++j) {
if (distance[j] == INF) {
is_connected = false;
break;
}
max_distance = max(max_distance, distance[j]);
}
if (!is_connected) {
result = -1;
break;
}
result = max(result, max_distance);
}
cout << result;
}
return 0;
}
本题难点:(说实话是我已经忘记的一些基础知识)
1.邻接表的构建:
先将名字映射为索引int 便于邻接表构建
然后vector<vector<int>> adj构建邻接表
adj.push_back() 插入操作
adj高维代表结点 低维代表邻接点
2.如何遍历图的邻接表:
使用bfs能获得最短距离
首先队列插入起始节点
int v=q.front()
然后for(int u:adj[v])//遍历临界点
然后判断diatance[u]数组是否为INF
若为INF说明当前第一次被找到 distance=distance[v]+1;
//记得初始化开始元素的distance为0;
之后就是返回主函数啦
挑选max_distance 若INF 说明二者不是朋友 return -1
否则 result=max(max_distance,result);
QAQ,这就是本道题的大致思路 图的邻接表+dfs