求欧拉回路 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;
}

猜你喜欢

转载自www.cnblogs.com/captain1/p/9764232.html