- 题意:给出一张图,求出该图有几个连通块(一个点不算一个连通块),并求出所有连通块中有几个连通块是存在环
- 解析:求连通块用dfs或并查集均可做,这里主要是想记录一下怎么判断一个无向图中是否存在环(毕竟想了挺久)。主要思想还有通过dfs实现,不难发现,若一个无向图存在环(假设三个点a、b、c),在dfs搜索过程中,假设从a开始a -> b,b -> c若此时c -> a说明这三个点形成一个环,那此时的问题就是如何判断c是可以走到a,实际上:假若u -> v,若有一个结点x(x!=u),并且u曾经被访问过,说明该图中至少存在一个环
- 代码:
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N = 1005;
vector<int> g[N];
int t, n, m, flag = 0;
int vis[N];
void dfs(int x, int pre)
{
for(int i = 0; i < g[x].size(); i++)
{
int v = g[x][i];
if(v == pre) continue; //除去上一个结点
if(vis[v])
{
flag = 1; //除去上一个结点外仍访问到曾经访问到的结点,说明存在环
continue;
}
vis[v] = 1;
dfs(v, x);
}
}
int main()
{
cin >> t;
for(int o = 1; o <= t; o++)
{
memset(vis, 0, sizeof vis);
cin >> n >> m;
for(int i = 1; i <= n; i++)
g[i].clear();
for(int i = 1; i <= m; i++)
{
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
int cnt = 0, num = 0;
for(int i = 1; i <= n; i++)
{
if(!vis[i])
{
if(!g[i].size()) continue; //一个点排除
cnt ++;
dfs(i, i);
if(flag) num ++;
}
flag = 0;
}
printf("Night sky #%d: %d constellations, of which %d need to be fixed.\n\n", o, cnt, num);
}
return 0;
}