题目描述
该题的目的是要你统计图的连通分支数。
输入
每个输入文件包含若干行,每行两个整数i,j,表示节点i和j之间存在一条边。
输出
输出每个图的联通分支数。
样例输入 复制
1 4
4 3
5 5
样例输出 复制
2
分析:
本题要求求出图的连通分量,但也可以抽象为求不同点的集合数量。因此,有两种方法可以求解,一是生成图,再利用DFS或者BFS遍历,得出图的连通分量;二是设置并查集,不断把相连的点并在一起,最后得出集合的数量。
要点:
- 本题给出的点并不连贯,所以并不能直接用下标代表关键字,可以在结构体中增加数据项存储关键字,或者依然用下标代表关键字,但是增加一个哈希表或标志项来表示该点是否可用。在本题均采用结构体中增加数据项的方式,但是会稍加复杂点。
一:设置并查集
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
struct node{
int id, father;
node(int _id, int _father) : id(_id), father(_father){}
};
vector<node> N;
unordered_map<int, int> H;
int findfather(int a){
int ad = H[a] - 1;
int x = ad;
while(N[ad].father != ad){
ad = N[ad].father;
}
int z = x;
while(N[x].father != x){
x = N[x].father;
N[z].father = ad;
z = x;
}
return ad;
}
int main()
{
int a, b;
int maxindex = 1;
int cnt = 0;
while(cin >> a >> b){
if(H[a] == 0){
node n = node(a, maxindex - 1);
N.push_back(n);
H[a] = maxindex++;
cnt++;
}
if(H[b] == 0){
node n = node(b, maxindex - 1);
N.push_back(n);
H[b] = maxindex++;
cnt++;
}
if(a != b){
int fa = findfather(a);
int fb = findfather(b);
if(fa != fb){
N[fb].father = fa;
cnt--;
}
}
}
cout << cnt << '\n';
return 0;
}
二:利用DFS
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
unordered_map<int, int> mp;
unordered_map<int, bool> vis;
struct node{
int data;
vector<int> link;
node(int _d){
data = _d;
}
node(){}
};
vector<node> N;
void DFS(int a){
int da = mp[a] - 1;
vis[a] = true;
if(N[da].link.size() == 0) return;
for(int i = 0; i < N[da].link.size(); i++){
int temp = N[da].link[i];
if(vis[temp] == false){
DFS(temp);
}
}
}
int main()
{
int a, b;
while(cin >> a >> b){
if(mp[a] == 0){
node n = node(a);
N.push_back(n);
mp[a] = N.size();
vis[a] = false;
}
if(mp[b] == 0){
node n = node(b);
N.push_back(n);
mp[b] = N.size();
vis[b] = false;
}
N[mp[a] - 1].link.push_back(b);
N[mp[b] - 1].link.push_back(a);
}
int cnt = 0;
for(auto it = vis.begin(); it != vis.end(); it++){
if(it -> second == false){
cnt++;
DFS(it -> first);
}
}
cout << cnt << '\n';
return 0;
}