欧拉路径:图G中的一条路径,能够通过图中的每一条边,并且每条边仅通过一次。
欧拉回路:欧拉回路是指起点和终点相同的欧拉路。
对于无向图,所有边都是连通的
(1)存在欧拉路径的充分必要条件:度数为奇数的点只能是0个或者2个
(2)存在欧拉回路的充分必要条件:度数为奇数的只能是0个
2对于有向图,所有边都是连通的 (1)存在欧拉路径的充分必要条件:要么所有点的出度均等于入度,
要么除了两个点之外,其余所有点的出度等于入度,剩余的两个点:一个满足出度比入度多1(起点),另一个满足入度比出度多1(终点)(2)存在欧拉回路的充分必要条件:所有点的出度均等于入度
【模板】欧拉路径
题目描述
求有向图字典序最小的欧拉路径。
输入格式
第一行两个整数 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 N=100010;
int n,m,start=1;
int ind[N],outd[N],p[N];
vector<int>vec[N];
stack<int>st;
void dfs(int now)
{
for(int i=p[now];p[now]<vec[now].size();i++)
{
p[now]++;
//cout<<"p[now]:"<<p[now]<<' '<<vec[now].size()<<endl;
dfs(vec[now][i]);
}
st.push(now);
}
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
{
int from,to;
scanf("%d%d",&from,&to);
vec[from].push_back(to);
ind[to]++;
outd[from]++;
}
int flag=0;
for(int i=1;i<=n;i++)
{
sort(vec[i].begin(),vec[i].end());
//cout<<i<<' '<<ind[i]<<' '<<outd[i]<<endl;
if(ind[i]==outd[i]) continue;
//cout<<i<<' '<<ind[i]<<' '<<outd[i]<<endl;
else if(ind[i]==outd[i]+1) flag++;
else if(ind[i]==outd[i]-1) start=i,flag--;
else
{
cout<<"No";
return 0;
}
}
if(flag!=0)
{
cout<<"No";
return 0;
}
dfs(start);
while(st.size())
cout<<st.top()<<' ',st.pop();
return 0;
}
3 3
1 2
1 3
3 1
1 3 1 2
可以hack掉
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int n,m,start;
int ind[N],outd[N],p[N];
vector<int>vec[N];
void dfs(int now)
{
cout<<now<<' ';
for(int i=p[now];p[now]<vec[now].size();i++)
{
p[now]++;
//cout<<"p[now]:"<<p[now]<<' '<<vec[now].size()<<endl;
dfs(vec[now][i]);
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
{
int from,to;
scanf("%d%d",&from,&to);
vec[from].push_back(to);
ind[to]++;
outd[from]++;
}
int flag=0;
for(int i=1;i<=n;i++)
{
sort(vec[i].begin(),vec[i].end());
//cout<<i<<' '<<ind[i]<<' '<<outd[i]<<endl;
if(ind[i]==outd[i]) continue;
//cout<<i<<' '<<ind[i]<<' '<<outd[i]<<endl;
else if(ind[i]==outd[i]+1) flag++;
else if(ind[i]==outd[i]-1) start=i,flag--;
else
{
cout<<"No";
return 0;
}
}
if(flag!=0)
{
cout<<"No";
return 0;
}
dfs(start);
return 0;
}