莫欺少年穷,修魔之旅在这开始—>算法提高课题解
思路:
1. 无向图存在欧拉回路:度数必须全是偶数
2. 有向图存在欧拉回路:入度和出度必须相等
3. 有孤立点没关系,只要边全是连通的就行
#include<bits/stdc++.h>
using namespace std;
const int N = 100010, M = 400010;
int type,n,m;
int h[N],e[M],ne[M],idx;
int din[N],dout[N];
bool used[M];
int ans[M],cnt;
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;
//无向图还需要记录反向边
if(type==1) used[i^1]=true;
//计算该边的编号
int t;
if(type==1)
{
t=i/2+1;
//如果是奇数边,表示走反向边
if(i&1) t=-t;
}
else t=i+1;
//遍历下一条边
int j=e[i];
i=ne[i];
dfs(j);
//倒序存入
ans[++cnt]=t;
}
}
int main()
{
cin>>type>>n>>m;
memset(h,-1,sizeof h);
for(int i=0;i<m;i++)
{
int a,b;
cin>>a>>b;
add(a,b);
if(type==1) add(b,a);
dout[a]++,din[b]++;
}
//无向图存在欧拉回路:度数必须全是偶数
if(type==1)
{
for(int i=1;i<=n;i++)
if(dout[i]+din[i]&1)
{
puts("NO");
return 0;
}
}
//有向图存在欧拉回路:入度和出度必须相等
else
{
for(int i=1;i<=n;i++)
if(din[i]!=dout[i])
{
puts("NO");
return 0;
}
}
//找有边的点
for(int i=1;i<=n;i++)
if(h[i]!=-1)
{
dfs(i);
break;
}
if(cnt<m)
{
puts("NO");
return 0;
}
puts("YES");
for(int i=cnt;i;i--) cout<<ans[i]<<' ';
puts("");
return 0;
}