记录是否搜过这个位置,从1开始遍历没有搜过的点,使用深度优先搜索,将层数依次加1。如果搜索到一个已经搜过的点,则证明这个连通图内有环,环的顶点数等于这个点和其父节点的层数的差值加1,如果一个连通图内只存在一个环则是章鱼子图。
如果只有一个章鱼子图,则输出“Yes”,和环的顶点数,反之输出“No”和章鱼子图的个数。
注意:
1. 如果有一个环,想接触的两个点各自搜到对方一次,meet / 2 == 1,证明子图内有一个环
2. 多测数据 idx = 0
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include "bits/stdc++.h"
using namespace std;
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define fios ofstream("test.txt");cout.rdbuf(out.rdbuf())
#define INF 0x3f3f3f3f
#define MINF 2147483647
#define eps 1e-6
#define PI acos(-1)
#define lowbit(x) (x & (-x))
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int, int> PII;
#define x first
#define y second
const int N = 100010, M = N * 2;
int n, m;
int h[N], e[M], ne[M], idx;
int dis[N];
int meet;
int cnt;
int maxv;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
void dfs(int u, int fa, int d)
{
dis[u] = d;
for(int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if(j == fa) continue;
if(!dis[j])
dfs(j, u, d + 1);
else
{
maxv = abs(dis[j] - dis[u]) + 1;
meet++;
}
}
}
int main()
{
int T;
cin >> T;
while(T--)
{
idx= 0;
memset(h, -1, sizeof h);
memset(dis, 0, sizeof dis);
cnt = 0;
maxv = 0;
cin >> n >> m;
while(m--)
{
int a, b;
cin >> a >> b;
add(a, b), add(b, a);
}
for(int i = 1; i <= n; i++)
if(!dis[i])
{
meet = 0;
dfs(i, -1, 1);
meet /= 2;
if(meet == 1) cnt++;
}
if(cnt == 1) cout << "Yes " << maxv << endl;
else cout << "No " << cnt << endl;
}
return 0;
}