You are given an undirected graph consisting of m edges. Your task is to find the number of connected components which are cycles.
Here are some definitions of graph theory.
An undirected graph consists of two sets: set of nodes (called vertices) and set of edges. Each edge connects a pair of vertices. All edges are bidirectional (i.e. if a vertex a). An edge can't connect vertex with itself, there is at most one edge between a pair of vertices.
Two vertices v.
A connected component is a cycle if and only if its vertices can be reordered in such a way that:
- the first vertex is connected with the second vertex by an edge,
- the second vertex is connected with the third vertex by an edge,
- ...
- the last vertex is connected with the first vertex by an edge,
- all the described edges of a cycle are distinct.
A cycle doesn't contain any other edges except described above. By definition any cycle contains three or more vertices.
There are [5,11,9,15].
The first line contains two integer numbers 0≤m≤2⋅105) — number of vertices and edges.
The following ui,vi) in the list of edges.
Print one integer — the number of connected components which are also cycles.
5 4
1 2
3 4
5 4
3 5
1
17 15
1 8
1 12
5 11
11 9
9 15
15 5
4 13
3 13
4 3
10 16
7 10
16 7
14 3
14 4
17 6
2
In the first example only component [3,4,5] is also a cycle.
The illustration above corresponds to the second example.
题目大意:求单圈环的个数【单圈环就是只有一个圈的环...】
题目分析:观察单圈环的可以发现它的一个性质每个点的度都是2,所以
【方法一】只需要用dfs遍历一下所有连在一起点,查看点的度是不是为2
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define f first 5 #define s second 6 #define ll long long 7 const int maxn=3e5; 8 vector<int>v[maxn]; 9 int vis[maxn]; 10 int ans,flag; 11 void dfs(int now,int fa) 12 { 13 vis[now]=1; 14 if(v[now].size()!=2)flag=1; 15 for(auto i:v[now]) 16 { 17 if(i==fa||vis[i])continue; 18 dfs(i,now); 19 } 20 } 21 22 int main() 23 { 24 int n,m; 25 cin>>n>>m; 26 for(int i=0;i<m;i++) 27 { 28 int x,y; 29 cin>>x>>y; 30 31 v[x].push_back(y); 32 v[y].push_back(x); 33 } 34 for(int i=1;i<=n;i++) 35 { 36 flag=0; 37 int ok=0; 38 if(!vis[i])dfs(i,-1),ok=1; 39 if(flag==0&&ok==1)ans++; 40 } 41 cout<<ans; 42 return 0; 43 }
【方法二】
方法一中的dfs仅仅是寻找连在一起的点,其实寻找一个连通块连在一起的点只需要使用并查集就能解决,以下是并查集+判断度是不是为2
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 const int maxn=200005; 7 int fa[maxn]; 8 vector<int>qwq[maxn]; 9 vector<int>orz[maxn]; 10 int find(int x) 11 { 12 int xx=x; 13 while(x!=fa[x]) 14 { 15 x=fa[x]; 16 } 17 while(fa[xx]!=x) 18 { 19 int t=fa[xx]; 20 fa[xx]=x; 21 xx=t; 22 } 23 return x; 24 } 25 int main() 26 { 27 int n,k; 28 scanf("%d%d",&n,&k); 29 for(int i = 1 ; i <= n ;i++) 30 fa[i]=i; 31 while(k--) 32 { 33 int a,b; 34 scanf("%d%d",&a,&b); 35 qwq[a].push_back(b); 36 qwq[b].push_back(a); 37 int qaq1=find(a); 38 int qaq2=find(b); 39 if(qaq1!=qaq2); 40 fa[qaq1]=qaq2; 41 } 42 for(int i = 1 ; i <= n ; i++) 43 { 44 orz[find(i)].push_back(i);//利用连通块所有点的祖先来将联通块内部的点存在一起 45 } 46 int cnt=0; 47 for(int i = 1 ; i <= n ; i++) 48 { 49 if(orz[i].size()>2) 50 { 51 bool or2=1; 52 for(int j = 0 ; j < orz[i].size()&&or2;j++) 53 { 54 if(qwq[orz[i][j]].size()!=2)or2=0; 55 } 56 if(or2)cnt++; 57 } 58 } 59 printf("%d\n",cnt); 60 return 0; 61 }