DTOJ#5186. 徒

给一个简单连通无向图,选定一个点作为起点,每次选一条未走过的边走过去,如果没有则停止。

问是否存在一个起点,无论如何选择,走出来的路径一定是欧拉路(即经过所有边恰好一次的路径)。

第一行一个整数 T T T,表示测试数据组数。

接下来对于每一组测试数据,第一行两个整数 n n n m m m 表示图中的点数与边数。

接下来 m m m 行,每行两个正整数 u u u v v v 表示图中的一条无向边。

保证给定的图连通且无重边与自环。

一行,为 YES 表示这样的点存在,不存在则为 NO

对于所有数据,保证 T ≤ 10 T\leq10 T10

子任务编号 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;
}

猜你喜欢

转载自blog.csdn.net/CSDNzhanghongyu/article/details/110094723