题目描述
该题的目的是要你统计图的连通分支数。
输入
每个输入文件包含若干行,每行两个整数i,j,表示节点i和j之间存在一条边。
输出
输出每个图的联通分支数。
样例输入
1 4
4 3
5 5
样例输出
2
思路一:利用并查集,连通分支数相当于集合数量。
#include <cstdio>
#include <unordered_set>
using namespace std;
const int maxn = 200010;
int father[maxn]; //存放父亲结点
unordered_set<int> st;
//初始化
void init() {
for (int i = 1; i <= maxn; i++) {
father[i] = i;
}
}
// findFather函数返回元素x所在集合的根结点
int findFather(int x) {
int a = x;
while (x != father[x]) {
x = father[x];
}
//路径压缩(可不写)
while (a != father[a]) {
int z = a;
a = father[a];
father[z] = x;
}
return x;
}
//合并a和b所在集合
void Union(int a, int b) {
int fA = findFather(a);
int fB = findFather(b);
if (fA != fB) {
father[fA] = fB;
}
}
int main() {
int a, b;
init();
while (scanf("%d%d", &a, &b) != EOF) {
Union(a, b);
st.insert(a);
st.insert(b);
}
int ans = 0; //集合数量
for (auto it = st.begin(); it != st.end(); it++) {
if (father[*it] == *it) ans++; //根结点
}
printf("%d", ans);
return 0;
}
思路二:基于邻接表的深度优先遍历。
#include <cstdio>
#include <vector>
#include <unordered_set>
using namespace std;
const int maxn = 200010;
vector<int> Adj[maxn];
unordered_set<int> st;
bool vis[maxn] = {0};
void DFS(int u) {
vis[u] = true;
for (int i = 0; i < Adj[u].size(); i++) {
if (!vis[Adj[u][i]]) {
DFS(Adj[u][i]);
}
}
}
void DFSTrave() {
int sum = 0;
for (auto it = st.begin(); it != st.end(); it++) {
if (!vis[*it]) {
DFS(*it);
sum++;
}
}
printf("%d", sum);
}
int main() {
int a, b;
while (scanf("%d%d", &a, &b) != EOF) {
Adj[a].push_back(b);
Adj[b].push_back(a);
st.insert(a);
st.insert(b);
}
DFSTrave();
return 0;
}
6846

被折叠的 条评论
为什么被折叠?



