欧拉回路(笔记)

【模板】欧拉路径

题目描述

求有向图字典序最小的欧拉路径。

输入格式

第一行两个整数 n , m n,m n,m 表示有向图的点数和边数。

接下来 m m m 行每行两个整数 u , v u,v u,v 表示存在一条 u → v u\to v uv 的有向边。

输出格式

如果不存在欧拉路径,输出一行 No

否则输出一行 m + 1 m+1 m+1 个数字,表示字典序最小的欧拉路径。

样例 #1

样例输入 #1

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

样例输出 #1

1 2 1 3 3 4 2

样例 #2

样例输入 #2

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

样例输出 #2

1 2 3 4 3 5

样例 #3

样例输入 #3

4 3
1 2
1 3
1 4

样例输出 #3

No

提示

对于 50 % 50\% 50% 的数据, n , m ≤ 1 0 3 n,m\leq 10^3 n,m103

对于 100 % 100\% 100% 的数据, 1 ≤ u , v ≤ n ≤ 1 0 5 1\leq u,v\leq n\leq 10^5 1u,vn105 m ≤ 2 × 1 0 5 m\leq 2\times 10^5 m2×105

保证将有向边视为无向边后图连通。
​​​​在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
const int MAX=100010;
int n,m,u,v,del[MAX];
int du[MAX][2]; 
stack <int> st;
vector <int> G[MAX];
void dfs(int now)
{
	for(int i=del[now];i<G[now].size();i=del[now])
	{ 
		del[now]=i+1;
		dfs(G[now][i]);
	}
	st.push(now);
}
int main()
{
	scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++) scanf("%d%d",&u,&v),G[u].push_back(v),du[u][1]++,du[v][0]++;  
    for(int i=1;i<=n;i++) sort(G[i].begin(),G[i].end());
    int S=1,cnt[2]={0,0}; 
    bool flag=1; 
    for(int i=1;i<=n;i++)
	{
        if(du[i][1]!=du[i][0]) flag=0;
        if(du[i][1]-du[i][0]==1) cnt[1]++,S=i;
        if(du[i][0]-du[i][1]==1) cnt[0]++;
    }
    if((!flag)&&!(cnt[0]==cnt[1]&&cnt[0]==1)) return !printf("No");
    dfs(S);
    while(!st.empty()) printf("%d ",st.top()),st.pop();
    return 0; 
}
posted @ 2022-09-24 21:16  zyc_xianyu  阅读(17)  评论(0编辑  收藏  举报