说实话,我以为这道题很简单,一看就知道用什么,可是在调试的时候疯了,都怪自己太菜了。要是能多想想就好了,每次都这样,非常不爽。好气😭
给定一个 n 个点 m 条边的无向图。
点的编号从 1 到 n。
图中不含重边和自环。
请你对给定图进行判断,如果该图是一个有且仅有一个环的连通图,则输出 YES
,否则输出 NO
。
输入格式
第一行包含两个整数 n,m。
接下来 m 行,每行包含两个整数 a,b,表示点 a 和点 b 之间存在一条无向边。
输出格式
如果该图是一个有且仅有一个环的连通图,则输出 YES
,否则输出 NO
。
数据范围
前三个测试点满足 1≤n≤10
所有测试点满足 1≤n≤100,0≤m≤n(n−1)2,1≤a,b≤n。
输入用例:
6 6
6 3
6 4
5 1
2 5
1 4
5 4
6 5
5 6
4 6
3 1
5 1
1 2
输出:
YES
NO
时间复杂度:线性
方法一:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110;
int n,m,cnt;
int p[N];
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main()
{
cin>>n>>m;
if(n!=m)puts("NO");
else
{
for (int i = 1; i <= n; i ++ )
p[i]=i;
cnt=n;
while (m -- )
{
int a,b;
cin>>a>>b;
if(find(a)!=find(b))
{
cnt--;
p[find(a)]=find(b);
}
}
if(cnt==1)puts("YES");
else puts("NO");
}
return 0;
}
方法二:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 110,M = 10010;
int h[N], e[M], ne[M], idx;
bool st[N];
int n,m;
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
bool spfa()
{
int sum=0;
queue<int> q;
q.push(1);
st[1]=true;
while(q.size())
{
int t=q.front();
q.pop();
sum++;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(!st[j])
{
st[j]=true;
q.push(j);
}
}
}
if(sum==n)
return true;
else
return false;
}
int main()
{
cin>>n>>m;
int t=m;
memset(h, -1, sizeof h);
while (m -- ){
int a,b;
cin>>a>>b;
add(a, b);
add(b, a);
}
bool flag=spfa();
if((n==t)&&flag)
puts("YES");
else
puts("NO");
return 0;
}
心得:当时真的没想那么多,结果就是活该,没考虑周全。我没考虑点数和变数的关系,下手之前我必须要想想,否则只会浪费时间。 (希望读者别学我,我太蠢了)🐖
来自一只极度痛苦的猪的发言