1184. 欧拉回路

题目链接

1184. 欧拉回路

给定一张图,请你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次。

输入格式

第一行包含一个整数 \(t,t∈{1,2}\),如果 \(t=1\),表示所给图为无向图,如果 \(t=2\),表示所给图为有向图。

第二行包含两个整数 \(n,m\),表示图的结点数和边数。

接下来 \(m\) 行中,第 \(i\) 行两个整数 \(v_i,\)u_i$,表示第 \(i\) 条边(从 \(1\) 开始编号)。

如果 \(t=1\) 则表示 \(v_i\)\(u_i\) 有一条无向边。
如果 \(t=2\) 则表示 \(v_i\)\(u_i\) 有一条有向边。
图中可能有重边也可能有自环。

点的编号从 \(1\)\(n\)

输出格式

如果无法一笔画出欧拉回路,则输出一行:NO

否则,输出一行:YES,接下来一行输出 任意一组 合法方案即可。

如果 \(t=1\),输出 \(m\) 个整数 \(p_1,p_2,…,p_m\)。令 \(e=|p_i|\),那么 \(e\) 表示经过的第 \(i\) 条边的编号。如果 \(p_i\) 为正数表示从 \(v_e\) 走到 \(u_e\),否则表示从 \(u_e\) 走到 \(v_e\)
如果 \(t=2\),输出 \(m\) 个整数 \(p_1,p_2,…,p_m\)。其中 \(p_i\) 表示经过的第 \(i\) 条边的编号。

数据范围

\(1≤n≤10^5\),
$0≤m≤2×10^5

输入样例1:

1
3 3
1 2
2 3
1 3

输出样例1:

YES
1 2 -3

输入样例2:

2
5 6
2 3
2 5
3 4
1 2
4 2
5 1

输出样例2:

YES
4 1 3 5 2 6
  • 时间复杂度:\(O(n+m)\)

代码

// Problem: 欧拉回路
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/1186/
// Memory Limit: 64 MB
// Time Limit: 1000 ms

// %%%Skyqwq
#include <bits/stdc++.h>

#define pb push_back
#define fi first
#define se second
#define mp make_pair
using namespace std;

typedef long long LL;
typedef pair<int, int> PII;

template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }

template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=1e5+5,M=4e5+5;
int h[N],e[M],ne[M],idx;
int type,n,m,din[N],dout[N],res[M],cnt;
bool used[M];
void add(int a,int b)
{
	e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int u)
{
	for(int &i=h[u];~i;)
	{
		if(used[i])
		{
			i=ne[i];
			continue;
		}
		used[i]=true;
		if(type==1)used[i^1]=true;
		int t=i+1;
		if(type==1)
		{
			t=i/2+1;        
			if(i&1)t=-t;
		}
		int j=e[i];
		i=ne[i];
		dfs(j);
		res[++cnt]=t;
	}
}
int main()
{
	memset(h,-1,sizeof h);
	scanf("%d",&type);
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		dout[u]++,din[v]++;
		add(u,v);
		if(type==1)add(v,u);
	}
	if(type==1)
	{
		for(int i=1;i<=n;i++)
			if((din[i]+dout[i])&1)
			{
				puts("NO");
				return 0;
			}
	}
	else
	{
		for(int i=1;i<=n;i++)
			if(din[i]!=dout[i])
			{
				puts("NO");
				return 0;
			}
	}
	for(int i=1;i<=n;i++)
		if(h[i]!=-1)
		{
			dfs(i);
			break;
		}
	if(cnt<m)
	{
	    puts("NO");
	    return 0;
	}
	puts("YES");
	for(int i=cnt;i;i--)printf("%d ",res[i]);
	return 0;
}
posted @ 2022-01-27 13:35  zyy2001  阅读(58)  评论(0编辑  收藏  举报