366. 看牛

题目链接

366. 看牛

给定 \(N\) 个点 \(M\) 条边的无向图,求一条路径,从节点 \(1\) 出发,最后回到节点 \(1\),并且满足每条边恰好被沿着正、反两个方向分别经过一次。

若有多种方案,输出任意一种即可。

输入格式

第一行包含两个整数 \(N\)\(M\)

接下来 \(M\) 行每行包含两个整数 \(a\)\(b\),表示点 \(a\) 和点 \(b\) 之间存在一条边。

输出格式

\(2M+1\) 行,每行包含一个整数,共同描述除了满足条件的一条路径。

数据范围

\(1≤N≤10^4\),
\(1≤M≤5∗10^4\)

输入样例:
4 5
1 2
1 4
2 3
2 4
3 4

输出样例:

1
2
3
4
2
1
4
3
2
4
1

解题思路

欧拉回路

按题意,每条边都得经过一次,说明是一条欧拉回路

  • 时间复杂度:\(O(n+m)\)

代码

// Problem: 看牛
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/368/
// 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=1e4+5,M=1e5+5;
int h[N],e[M],ne[M],idx;
int n,m,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;
		used[i^1]=true;
		int j=e[i];
		res[++cnt]=u;
		i=ne[i];
		dfs(j);
		res[++cnt]=j;
	}
}
int main()
{
	memset(h,-1,sizeof h);
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		add(u,v),add(v,u);
	}
	dfs(1);
	res[++cnt]=1;
	for(int i=1;i<=cnt;i++)printf("%d\n",res[i]);
	return 0;	
}
posted @ 2022-01-27 14:14  zyy2001  阅读(62)  评论(0编辑  收藏  举报