链接:http://uoj.ac/problem/117
题目描述
有一天一位灵魂画师画了一张图,现在要你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次。
一共两个子任务:
- 这张图是无向图。(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 ,输出 m 个整数 p1,p2,…,pm 。令 e=∣pi∣ ,那么 e 表示经过的第 i 条边的编号。如果 pi 为正数表示从 ve 走到 ue ,否则表示从 ue 走到 ve 。
- 如果 t=2 ,输出 m 个整数 p1,p2,…,pm 。其中 pi 表示经过的第 i 条边的编号。
-
样例一
input
1 3 3 1 2 2 3 1 3
output
YES 1 2 -3
样例二
input
2 5 6 2 3 2 5 3 4 1 2 4 2 5 1
output
YES 4 1 3 5 2 6
限制与约定
1≤n≤105,0≤m≤2×105
时间限制: 1s
空间限制: 256MB
特别裸的欧拉回路,没什么好分析的,直接用套圈法解决,但是以前学习欧拉回路时候的那个博客没找到,等有时间找到在补发分析。。。 - 代码:
#include <cstdio> #include <cstring> #define ele int using namespace std; #define maxn 100010 #define maxm 400010 struct edge{ ele v; bool ban; edge *nxt; }ep[maxm]; ele t,n,m,ecnt,cnt,ind[maxn],outd[maxn],ans[maxm]; edge *g[maxn]; inline void addedge(ele u,ele v){ edge *p=&ep[ecnt++]; p->v=v; p->ban=false; p->nxt=g[u]; g[u]=p; } inline edge* rev(edge *j){ ele i=j-ep; return ep+(i^1); } void dfs_ud(ele i){ while (g[i]) if (!g[i]->ban){ edge *j=g[i]; j->ban=true; rev(j)->ban=true; dfs_ud(j->v); ele tmp=j-ep; if (tmp&1) tmp=-(tmp/2+1); else tmp=tmp/2+1; ans[cnt++]=tmp; } else g[i]=g[i]->nxt; } void dfs_d(ele i){ while (g[i]) if (!g[i]->ban){ edge *j=g[i]; j->ban=true; dfs_d(j->v); ans[cnt++]=j-ep+1; } else g[i]=g[i]->nxt; } int main(){ scanf("%d%d%d",&t,&n,&m); ecnt=0; memset(g,0,sizeof(g)); memset(ind,0,sizeof(ind)); memset(outd,0,sizeof(outd)); for (int i=0; i<m; ++i){ ele u,v; scanf("%d%d",&u,&v); --u,--v; addedge(u,v); ++outd[u]; ++ind[v]; if (t==1) addedge(v,u),++outd[v],++ind[u]; } cnt=0; if (t==1){ bool flag=true; for (int i=0; i<n; ++i) if (ind[i]&1){ flag=false; break; } if (!flag) puts("NO"); else{ for (int i=0; i<n; ++i){ dfs_ud(i); if (cnt) break; } if (cnt==m){ puts("YES"); for (int i=cnt-1; i>=0; --i) printf("%d ",ans[i]); puts(""); } else puts("NO"); } } else{ edge *p=g[0]; while (p) p=p->nxt; bool flag=true; for (int i=0; i<n; ++i) if (ind[i]!=outd[i]){ flag=false; break; } if (!flag) puts("NO"); else{ for (int i=0; i<n; ++i){ dfs_d(i); if (cnt) break; } if (cnt==m){ puts("YES"); for (int i=cnt-1; i>=0; --i) printf("%d ",ans[i]); puts(""); } else puts("NO"); } } return 0; }