【题目】
题目描述:
有一天一位灵魂画师画了一张图,现在要你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次。
一共两个子任务:
- 这张图是无向图。(50分)
- 这张图是有向图。(50分)
输入格式:
第一行一个整数 ,表示子任务编号。,如果 则表示处理无向图的情况,如果 则表示处理有向图的情况。
第二行两个整数 ,表示图的结点数和边数。
接下来 行中,第 行两个整数 ,表示第 条边(从 1 开始编号)。保证 1 ≤ ≤ 。
- 如果 则表示 到 有一条无向边。
- 如果 则表示 到 有一条有向边。
图中可能有重边也可能有自环。
输出格式:
如果不可以一笔画,输出一行 “NO”。
否则,输出一行 “YES”,接下来一行输出一组方案。
- 如果 ,输出 个整数 ,,…,。令 ,那么 表示经过的第 条边的编号。如果 为正数表示从 走到 ,否则表示从 走到 。
- 如果 ,输出 个整数 ,,…,。其中 表示经过的第 条边的编号。
样例数据:
【样例1】
输入
1 3 3 1 2 2 3 1 3
输出
YES 1 2 -3
【样例2】
输入
2 5 6 2 3 2 5 3 4 1 2 4 2 5 1
输出
YES 4 1 3 5 2 6
限制与约定:
本题有 SPJ
1 ≤ ≤ ,0 ≤ ≤
【分析】
今天终于学会欧拉回路了,开心
这道题就是欧拉回路的板题啦,并不难,就不做单独解释了
【代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define M 500005
#define wrong {printf("NO");return 0;}
using namespace std;
int n,m,t,size;
int in[N],out[N],ans[N];
int num=1,v[M],next[M],first[N];
bool vis[M];
void add(int x,int y)
{
num++;
next[num]=first[x];
first[x]=num;
v[num]=y;
}
void dfs(int x)
{
for(int &i=first[x];i;i=next[i])
{
int j=v[i],flag=i%2;
int e=(t==1?i/2:i-1);
if(vis[e]) continue;
vis[e]=true,dfs(j);
if(t==1&&flag) ans[++size]=-e;
else ans[++size]=e;
}
}
int main()
{
int x,y,i,j;
scanf("%d%d%d",&t,&n,&m);
for(i=1;i<=m;++i)
{
scanf("%d%d",&x,&y);
add(x,y);out[x]++,in[y]++;
if(t==1) add(y,x);
}
for(i=1;i<=n;++i)
{
if(t==1&&(in[i]+out[i])%2) wrong;
if(t==2&&in[i]!=out[i]) wrong;
}
for(i=1;i<=n;++i)
{
if(first[i])
{
dfs(i);
break;
}
}
if(size!=m) wrong;
printf("YES\n");
for(i=size;i>=1;--i)
printf("%d ",ans[i]);
return 0;
}