知识点:广度优先搜索
这个题应该是顶级里面最简单的一道题,用到的知识只有广搜,看题目是时间是1秒,数据的规模是10的三次方,发现用n方的复杂度就可以过,然后发现题目要求联通块的个数,两种搜索都可以,但是第二个问题求的是图里面的最长最短路,无权图最短路用广搜再适合不过,所以就这么写了,
每次广搜找出这个点在它联通的图里面最长的最短路,更新答案即可,一句话概括就是暴力广搜,然后同时记录第一个答案,需要注意一点的是,题目的边数一定要开到合适的大小,不然就会段错误,也就是无向完全图和有向完全图的边数是多少,
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int tot, ver[N * N], nxt[N * N], head[N], ans, vis[N];
void add(int x, int y) {
ver[++tot] = y;
nxt[tot] = head[x]; head[x] = tot;
}
void bfs(int x) {
int dist[N];
memset(dist, -1, sizeof(dist));
dist[x] = 0;
queue<int> q;
q.push(x);
while (!q.empty()) {
int now = q.front(); q.pop();
vis[now] = 1;
ans = max(ans, dist[now] - 1);
for (int i = head[now]; i; i = nxt[i]) {
int y = ver[i];
if (dist[y] != -1) continue;
q.push(y);
dist[y] = dist[now] + 1;
}
}
}
int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
int k;
cin >> k;
for (int j = 0; j < k; j++) {
int x;
cin >> x;
int ok = 1;
for (int u = head[i]; u; u = nxt[u]) {
int y = ver[u];
if (y == x) ok = 0;
}
if (!ok) continue;
add(i, x); add(x, i);
}
}
int cnt = 0;
for (int i = 1; i <= n; i++) {
if (!vis[i]) cnt++;
bfs(i);
}
cout << cnt << " " << ans;
return 0;
}