#欧拉回路#AT4518 [AGC032C] Three Circuits

题目

给定一个 \(n\) 个点,\(m\) 条边的简单无向连通图,

问是否能将边分成三部分,使每部分都能成为环


分析

每个点的度数都得为偶数,这不由得想到了欧拉回路。

如果整张图是一个简单环那么一定无解。

如果存在一个点的度数大于等于 6,也就是通过这个点可以产生至少 3 个环。

那么剩下讨论点的度数为 4 的情况,如果只有一个度数为 4 的点显然无解。

如果个数超过 2,那么一定可以拆成 3 个环。

剩下就是个数正好为 2 的情况,如果度数为 4 的两个点本身有两个环就可以拆成 3 个环。

否则只剩下这两个点连接四条链的情况,一定无解。

可以先割掉两个度数为 4 的点判断每个点是否能只与其中一点连通


代码

#include <cstdio>
#include <cctype>
using namespace std;
const int N=100011;
struct node{int y,next;}e[N<<1];
int v[N],as[N],n,m,deg[N],four,fi,se,et=1;
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
void dfs(int x){
	v[x]=1;
	for (int i=as[x];i;i=e[i].next)
	if (v[e[i].y]==-1) se=fi,fi=e[i].y;
	    else if (!v[e[i].y]) dfs(e[i].y);
}
int main(){
	n=iut(),m=iut();
	for (int i=1;i<=m;++i){
		int x=iut(),y=iut();
		e[++et]=(node){y,as[x]},as[x]=et,++deg[x];
		e[++et]=(node){x,as[y]},as[y]=et,++deg[y];
	}
	for (int i=1;i<=n;++i)
	    if (deg[i]&1) return !puts("No");
	for (int i=1;i<=n;++i)
	    if (deg[i]>=6) return !puts("Yes");
	for (int i=1;i<=n;++i)
	    if (deg[i]>=4) se=fi,fi=i,++four;
	if (four!=2) return !puts(four<2?"No":"Yes");
	v[fi]=v[se]=-1;
	for (int i=1;i<=n;++i)
	if (!v[i]){
		fi=se=0,dfs(i);
		if (fi==se) return !puts("Yes");
	}
	return !puts("No");
} 
posted @ 2021-11-13 16:01  lemondinosaur  阅读(51)  评论(0)    收藏  举报