UOJ #117.欧拉回路
Description
有一天一位灵魂画师画了一张图,现在要你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次。
一共两个子任务:
- 这张图是无向图。(50分)
- 这张图是有向图。(50分)
Solution
有向图中出度等于入度,无向图中度数为偶数就有欧拉回路
需要特判图是否联通
还需要动态地更新head以保证不去查询已经走过的边
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> using namespace std; int t,n,m,fa[100005],head[100005],tot=1,id[100005],od[100005],sta[100005],top,s; bool vst[200005]; struct Edge { int to,nxt,w; }edge[400005]; inline int read() { int f=1,w=0; char ch=0; while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=getchar(); return f*w; } int find(int x) { return (fa[x]==x)?fa[x]:fa[x]=find(fa[x]); } void dfs(int k) { for(int i=head[k];i;) if(vst[i>>1]) head[k]=edge[i].nxt,i=edge[i].nxt; else vst[i>>1]=true,dfs(edge[i].to),sta[++top]=edge[i].w,i=head[k]; } int main() { t=read(),n=read(),m=read(); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) { int u=read(),v=read(); fa[find(u)]=find(v); if(t==1) edge[++tot]=(Edge){v,head[u],i},head[u]=tot,edge[++tot]=(Edge){u,head[v],-i},head[v]=tot,id[u]++,id[v]++; else edge[++tot]=(Edge){v,head[u],i},head[u]=tot,++tot,id[v]++,od[u]++; } if(t==1) for(int i=1;i<=n;i++) if(id[i]&1) return puts("NO"),0;else; else for(int i=1;i<=n;i++) if(id[i]!=od[i]) return puts("NO"),0; for(int i=1;i<=n;i++) if(id[i]) s=i; for(int i=1;i<=n;i++) if(id[i]&&find(i)!=find(s)) return puts("NO"),0; dfs(s),puts("YES"); for(int i=top;i;i--) printf("%d ",sta[i]); return 0; }