给一个简单连通无向图,选定一个点作为起点,每次选一条未走过的边走过去,如果没有则停止。
问是否存在一个起点,无论如何选择,走出来的路径一定是欧拉路(即经过所有边恰好一次的路径)。
第一行一个整数 T T T,表示测试数据组数。
接下来对于每一组测试数据,第一行两个整数 n n n 和 m m m 表示图中的点数与边数。
接下来 m m m 行,每行两个正整数 u u u 和 v v v 表示图中的一条无向边。
保证给定的图连通且无重边与自环。
一行,为 YES
表示这样的点存在,不存在则为 NO
。
对于所有数据,保证 T ≤ 10 T\leq10 T≤10。
子任务编号 | n ≤ n\leq n≤ | m ≤ m\leq m≤ | 分值 |
---|---|---|---|
1 1 1 | 5 5 5 | 10 10 10 | |
2 2 2 | 20 20 20 | 20 20 20 | |
3 3 3 | 1000 1000 1000 | 30 30 30 | |
4 4 4 | 10000 10000 10000 | 20000 20000 20000 | 20 20 20 |
5 5 5 | 100000 100000 100000 | 200000 200000 200000 | 20 20 20 |
ahsdfz noip2020模拟
题解:
先判断 E u l e r Euler Euler 路。但是不一定满足一定合法。
这时我们发现若有一个点被所有环包含,那以这个点为起点就合法。
证明考虑反证。
若不合法,必然存在剩余的环,不满足条件。
度数为奇数的点同理。
#include<bits/stdc++.h>
#define N 100005
using namespace std;
int read(){
int op=1,sum=0;
char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-') op=-1;ch=getchar();}
while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+ch-'0',ch=getchar();
return op*sum;
}
int st[N<<1],ed[N<<1],fa[N];
int n,m;
inline int get(int x){
return fa[x]==x?x:fa[x]=get(fa[x]);}
inline int pd(int x){
for(int i=1;i<=n;++i)fa[i]=i;
for(int i=1;i<=m;++i){
if(st[i]==x||ed[i]==x)continue;
int fx=get(st[i]),fy=get(ed[i]);
if(fx==fy)return 0;
fa[fx]=fy;
}
return 1;
}
int d[N];
int main(){
int T=read();
while(T--){
n=read(),m=read();memset(d,0,sizeof(d));
for(int i=1;i<=m;++i){
st[i]=read(),ed[i]=read();
d[st[i]]++;d[ed[i]]++;
}
int cnt=0;
for(int i=1;i<=n;++i){
if(d[i]&1)++cnt;
}
if(cnt>2){
puts("NO");continue;}
if(cnt==0){
int pos=0;
for(int i=1;i<=n;++i)if(d[pos]<d[i])pos=i;
if(pd(pos))puts("YES");
else puts("NO");
}else{
int flag=0;
for(int i=1;i<=n;++i){
if(d[i]&1){
flag|=pd(i);
}
}
if(flag)puts("YES");
else puts("NO");
}
}
return 0;
}