1. 程式人生 > 其它 >#歐拉回路#AT4518 [AGC032C] Three Circuits

#歐拉回路#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");
}