求欧拉回路 UOJ117
传送门
什么是欧拉回路呢……?欧拉回路的定义就是从vi出发到vi,经过每条边有且只有一次的路径。
就很像一笔画。
欧拉回路的性质较多……定理也很多……直接证明很长……我们还是直接说怎么判定,怎么求欧拉回路吧。
无向图:每个点的度不为奇数。
有向图:每个点的入度和出度相同。
如果不符合以上要求,那么图中将不存在欧拉回路。当然,如果图不连通也是不存在的。
至于怎么求的话,我们采用dfs的搜索方法,每次枚举一条边,如果这条边当前没被标记过,那就标记这条边,并且继续向下深搜,把经过的边压入栈,最后返回的时候输出就可以啦。
这道题同时要求实现有向图和无向图,无向图就是多建了一些边,然后在返回输出的时候会有负数的处理。
看一下代码。
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<set> #include<queue> #include<vector> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define pb push_back #define enter putchar('\n') using namespace std; typedef long long ll; const int M = 100005; const int N = 200005; const int INF = 1000000009; int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } struct edge { int next,to; }e[N<<1]; int t,n,m,ecnt = 1,cdeg[M],rdeg[M],x,y,head[N],ans[N],cnt,a,b; bool vis[N<<1]; void add(int x,int y) { e[++ecnt].to = y; e[ecnt].next = head[x]; head[x] = ecnt; } void dfs(int x) { for(int &i = head[x];i;i = e[i].next) { int k = e[i].to,j = i; if(!vis[j]) { vis[j] = vis[j^1] = 1; dfs(k); ans[++cnt] = j; } } } int main() { t = read(),n = read(),m = read(); rep(i,1,m) { a = read(),b = read(),add(a,b); if(t == 1) add(b,a),rdeg[a]++,cdeg[b]++; else ecnt++,rdeg[b]++,cdeg[a]++; } if(t == 1) { rep(i,1,n) if((rdeg[i] + cdeg[i]) & 1) printf("NO\n"),exit(0); } else { rep(i,1,n) if(rdeg[i] != cdeg[i]) printf("NO\n"),exit(0); } dfs(a); if(cnt != m) printf("NO\n"); else { printf("YES\n"); per(i,cnt,1) printf("%d ",ans[i]&1?-(ans[i]>>1):(ans[i]>>1)); } return 0; }
当你意识到,每个上一秒都成为永恒。