UOJ #488. 欧拉回路
题目描述:
有一天一位灵魂画师画了一张图,现在要你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次。
一共两个子任务:
这张图是无向图。( 50分)
这张图是有向图。( 50分)
输入描述:
第一行一个整数 t,表示子任务编号。t∈{1,2},如果 t=1则表示处理无向图的情况,如果 t=2则表示处理有向图的情况。
第二行两个整数 n,m,表示图的结点数和边数。
接下来 m 行中,第 i 行两个整数 vi,ui,表示第 i 条边(从 1 开始编号)。保证 1≤vi,ui≤n。
如果 t=1 则表示 vi 到 ui 有一条无向边。
如果 t=2 则表示 vi 到 ui 有一条有向边。
图中可能有重边也可能有自环。
输出描述:
如果不可以一笔画,输出一行 “NO”。
否则,输出一行 “YES”,接下来一行输出一组方案。
如果 t=1,输出 mm 个整数 p1,p2,…,pm。令 e=|pi|,那么 e 表示经过的第 i 条边的编号。如果 pi 为正数表示从 ve 走到 ue,否则表示从 ue 走到 ve。
如果 t=2,输出 m 个整数 p1,p2,…,pm。其中 pi 表示经过的第 i 条边的编号。
样例输入1:
1
3 3
1 2
2 3
1 3
样例输出1:
YES
1 2 -3
样例输入2:
2
5 6
2 3
2 5
3 4
1 2
4 2
5 1
样例输出2:
YES
4 1 3 5 2 6
时间限制、数据范围及描述:
时间:1s 空间:256M
1<=n<=10^5;0<=m<=2×10^5
思路:
欧拉回路模板题
代码:
#include<cmath> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=100010; const int M=1000010; bool flag[M]; int in[N],out[N]; int type,n,m,tot=1,x,y; int head[N],ver[M],nxt[M]; vector<int> ans; void add(int u,int v) { ver[++tot]=v; nxt[tot]=head[u]; head[u]=tot; } void dfs(int x) { for(int &i=head[x],y; y=ver[i],i; i=nxt[i]) { int c=(type==1?i/2:i-1); int sig=i%2; if(flag[c]) continue; flag[c]=1; dfs(y); if(type==1) ans.push_back(sig?-c:c); else ans.push_back(c); } } int main () { scanf("%d%d%d",&type,&n,&m); for(int i=1; i<=m; i++) { scanf("%d%d",&x,&y); add(x,y); if(type==1) add(y,x); out[x]++; in[y]++; } if(type==1) { for(int i=1; i<=n; i++) if((in[i]+out[i])%2) { printf("NO\n"); return 0; } } else for(int i=1; i<=n; i++) { if(in[i]!=out[i]) { printf("NO\n"); return 0; } } for(int i=1; i<=n; i++) if(head[i]) { dfs(i); break; } if(ans.size()!=m) { printf("NO\n"); return 0; } printf("YES\n"); for(int i=m-1; i>=0; i--) printf("%d ",ans[i]); printf("\n"); return 0; }