题解:
1、n个点m条边的无向图,问其中环的个数。
2、首先要知道的是一个环的定义是环内任意点的度都为2,也就是说不能有任何多余的分支
3、数据量很大,用邻接矩阵存图在DFS找环时会超时,所以这里用邻接表存储图
4、找环过程中每个点只需遍历一次,所以不需要取消标记
5、DFS找到同一个集合的点,然后通过判断所有点的度是否全为2来判断该集合的点是否成环
6、判断点的度可以用邻接表中每个点对应的大小即可
#include <bits/stdc++.h>
using namespace std;
const int maxn = 200000+10;
bool visited[maxn];
vector<int> G[maxn];
vector<int> di;
//找到有边的所有点,或者说同一个集合的点
void dfs(int tag){
visited[tag] = true; //不后退使用标记,避免重复寻找
di.push_back(tag); //存储同一个集合的点
for(int i=0;i<G[tag].size();i++) //遍历对应邻接表
if(visited[G[tag][i]] == false)
dfs(G[tag][i]);
}
int main(){
ios::sync_with_stdio(false); //cin加速
int n,m,u,v,j,cnt = 0;
cin >> n >> m;
for(int i=0;i<m;i++) {
cin >> u >> v;
G[u].push_back(v); //存储邻接表
G[v].push_back(u);
}
for(int i=1;i<=n;i++){
if(visited[i] == true) //避免重复寻找
continue;
di.clear(); //清空存储仓
dfs(i); //DFS起点
//判断是否成环(成环条件为同一集合内所有点的度都为2)
for(j=0;j<di.size();j++)
if(G[di[j]].size() != 2)
break;
if(j == di.size()) //全为2则计数器++
cnt++;
}
cout << cnt << endl;
return 0;
}