【模板】欧拉路径
题目描述
求有向图字典序最小的欧拉路径。
输入格式
第一行两个整数 n , m n,m n,m 表示有向图的点数和边数。
接下来 m m m 行每行两个整数 u , v u,v u,v 表示存在一条 u → v u\to v u→v 的有向边。
输出格式
如果不存在欧拉路径,输出一行 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,m≤103。
对于 100 % 100\% 100% 的数据, 1 ≤ u , v ≤ n ≤ 1 0 5 1\leq u,v\leq n\leq 10^5 1≤u,v≤n≤105, m ≤ 2 × 1 0 5 m\leq 2\times 10^5 m≤2×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;
}