AcWing 3225-csp6(4)欧拉路径. 送货
原题链接
中等
作者:
YAX_AC
,
2024-11-17 12:25:53
,
所有人可见
,
阅读 2
#include<iostream>
#include<algorithm>
#include<cstring>
#include<set>
using namespace std;
const int N = 10010,M = 100010;
/*题目中是无向图
对于无向图:
判断欧拉回路
1.连通
2.所有点的度数都是偶数
判断欧拉路径
1.连通
2.度数为奇数的点要么有两个(且起点含一个度数为奇数的点),要么有0个
对于有向图:
判断欧拉回路
1.连通
2.所有点的入度等于出度
判断欧拉路径
1.连通
2.要么所有点的入度等于出度
要么有一个点入度比出度多1,或者出度比入度多1
要保证最终的方案字典序最小:按照编号从小到大搜索所有边,即可保证字典序最小
*/
//用set和引用的技巧,可防止重复遍历的问题,降低时间复杂度
//用并查集判断是否连通
int n,m;
set<int> g[N];
int p[N];
int ans[M];//答案和边数相关M
int top;
int find(int x)
{
if(p[x]!=x) p[x] = find(p[x]);
return p[x];
}
void dfs(int u)
{
while(g[u].size())//枚举u所有相邻的点
{
int t = *g[u].begin();
g[u].erase(t),g[t].erase(u);//无向图,两边都得删
dfs(t);
}
ans[++top] = u;
}
int main()
{
cin>>n>>m;
for(int i = 1; i<=n; i++) p[i] = i;
while(m--)
{
int a,b;
cin>>a>>b;
g[a].insert(b),g[b].insert(a);//无向图插入两个方向
p[find(a)] = find(b);//合并两个点
}
//枚举一下度数为奇数点的个数
int s = 0;
for(int i = 1; i<=n; i++)
if(find(i) != find(1))//不连通
{
puts("-1");
return 0;
}
else if(g[i].size()%2) s++;
//题目要求从1号点走,即如果有奇数点的话,1号点的度数必须为奇数,1号点为偶数无解
if((s!=0 && s!=2) || (s==2 && g[1].size()%2==0))
{
puts("-1");
return 0;
}
dfs(1);
//回溯即方案的倒序
for(int i = top; i; i--)
cout<<ans[i]<<' ';
return 0;
}