「UOJ#117」 欧拉回路

欧拉回路 - 题目 - Universal Online Judge

题意:

给定有向图或无向图,求一条欧拉回路。


题解

心路历程:woc什么傻哔东西->哇真香我的吗!(逃

首先我知道很多人把欧拉回路和欧拉通路混为一谈,所以我以为这道题也是叫欧拉回路的欧拉迹

(欧拉迹比欧拉回路难打多少?!!!QAQ好吧也没多少

然后WA了2次才意识到这是真·欧拉回路。

改过来之后套版子上交:

//其中的dfs我是这么写的↓
void dfs(int x)
{
    for(int i=h[x];i;i=a[i].f)
    if(a[i].nod)
    {
        int x=a[i].nod;
        a[i].nod=0;
        a[i^1].nod=0;
        d[x]--;
        d[a[i].e]--;
        dfs(a[i].e);
        st.push(x);
    }
    return;
}

肥肠标准的Hierholzer嘛。

然后光荣TLE(妈妈你骗我 你不是说Hierholzer是$O(E)$吗QAQ?!!!)

直到我从网上看不懂的大佬题解中看到了一个关键词:

      当前弧优化

跟dinic里的当前弧优化一样,这里的当前弧优化也是为了避免每次重复循环很多次i

eg:

2
1 200000
1 1
1 1
1 1
1 1
...

在这种情况下,我们每一次dfs()时,就会重新走一遍差不多所有连着1的边......

也就是说被光荣卡成$O(E^2)$了。

怎么办呢?

只需要让h[x]跟着i动就行了鸭!

//已经经历过了的i是绝无再扩展的可能了,那不如把h[x]推到前面去

于是,魔改之后:

void dfs(int x)
{
    //for(R int i=h[x];i;i=a[i].f)
    while(h[x])
    {
    int i=h[x];
    h[x]=a[i].f;//更新h[x]
    //剩下来的就跟以前一样了
    if(a[i].nod)
    {
        int f=a[i].nod;
        a[i].nod=0;
        a[i^1].nod=0;
        d[x]--;
        d[a[i].e]--;
        dfs(a[i].e);
        st[++tos]=f;//换成了数组模拟的栈
    }
    }
    return;
}

时间直接变成原来的零头(3400ms+->32ms(n=1e5)

然后这道题就可以过掉啦。

  1 /*
  2 ID    题目    提交者    结果    用时    内存    语言    文件大小    提交时间    测评时间
  3 #288775    #117. 欧拉回路    qwerta    100    534ms    14912kb    C++    3.0kb    2018-09-30 16:29:45    2018-09-30 16:29:47
  4 */
  5 #include<iostream>
  6 #include<cstdio>
  7 #include<cmath>
  8 #include<stack>
  9 using namespace std;
 10 #define R register
 11 const int MAXN=1e5+3;
 12 const int MAXM=2e5+3;
 13 struct emm{
 14     int e,f,nod;
 15 }a[2*MAXM];
 16 int h[MAXN];
 17 int tot=1;
 18 inline void con(int x,int y,int k)
 19 {
 20     a[++tot].f=h[x];
 21     h[x]=tot;
 22     a[tot].e=y;
 23     a[tot].nod=k;
 24     return;
 25 }
 26 int d[MAXN];
 27 int st[10*MAXM];
 28 int tos=0;
 29 void dfs(int x)
 30 {
 31     //for(R int i=h[x];i;i=a[i].f)
 32     while(h[x])
 33     {
 34     int i=h[x];
 35     h[x]=a[i].f;
 36     if(a[i].nod)
 37     {
 38         int f=a[i].nod;
 39         a[i].nod=0;
 40         a[i^1].nod=0;
 41         d[x]--;
 42         d[a[i].e]--;
 43         dfs(a[i].e);
 44         st[++tos]=f;
 45     }
 46     }
 47     return;
 48 }
 49 int tim=0;
 50 void dfss(int x)
 51 {
 52     //cout<<tos<<endl;
 53     //for(R int i=h[x];i;i=a[i].f)
 54     while(h[x])
 55     {
 56     int i=h[x];
 57     h[x]=a[i].f;
 58     if(a[i].nod)
 59     {
 60         int f=a[i].nod;
 61         a[i].nod=0;
 62         d[x]--;
 63         d[a[i].e]--;
 64         dfss(a[i].e);
 65         st[++tos]=f;
 66     }
 67     }
 68     return;
 69 }
 70 int fa[MAXN];
 71 inline int fifa(int x)
 72 {
 73     if(fa[x]==x)return x;
 74     return fa[x]=fifa(fa[x]);
 75 }
 76 int rd[MAXN];
 77 int cd[MAXN];
 78 int main()
 79 {
 80     //freopen("a.in","r",stdin);
 81     int t;
 82     scanf("%d",&t);
 83     if(t==1)
 84     {
 85         int n,m;
 86         scanf("%d%d",&n,&m);
 87         for(R int i=1;i<=n;++i)
 88         fa[i]=i;
 89         for(R int i=1;i<=m;++i)
 90         {
 91             int u,v;
 92             scanf("%d%d",&u,&v);
 93             con(u,v,i);
 94             con(v,u,-i);
 95             d[u]++;
 96             d[v]++;
 97             fa[fifa(u)]=fifa(v);
 98         }
 99         //
100         for(R int i=1;i<=n;++i)
101         if(d[i]%2==1){cout<<"NO";return 0;}
102         int tag=0;
103         for(R int i=1;i<=n;++i)
104         if(d[i])
105         {
106             if(!tag)tag=fifa(i);
107             else if(fifa(i)!=tag){cout<<"NO";return 0;}
108         }
109         //
110         int s=-1;
111         for(R int i=1;i<=n;++i)
112         if(d[i]){s=i;break;}
113         dfs(s);
114         cout<<"YES"<<endl;
115         while(tos)
116         {
117             printf("%d ",st[tos]);
118             --tos;
119         }
120     }
121     else
122     {
123         int n,m;
124         scanf("%d%d",&n,&m);
125         for(R int i=1;i<=n;++i)
126         fa[i]=i;
127         for(R int i=1;i<=m;++i)
128         {
129             int u,v;
130             scanf("%d%d",&u,&v);
131             con(u,v,i);
132             cd[u]++;
133             rd[v]++;
134             fa[fifa(u)]=fifa(v);
135         }
136         //
137         for(R int i=1;i<=n;++i)
138         if(rd[i]!=cd[i]){cout<<"NO";return 0;}
139         int tag=0;
140         for(R int i=1;i<=n;++i)
141         if(rd[i]||cd[i])
142         {
143             if(!tag)tag=fifa(i);
144             else if(fifa(i)!=tag){cout<<"NO";return 0;}
145         }
146         //
147         int s=0;
148         for(R int i=1;i<=n;++i)
149         if(rd[i]||cd[i]){s=i;break;}
150         dfss(s);
151         cout<<"YES"<<endl;
152         while(tos)
153         {
154             printf("%d ",st[tos]);
155             --tos;
156         }
157     }
158     return 0;
159 }
160 //其实删欧拉通路和那些调试之前有200+行(逃

 

转载于:https://www.cnblogs.com/qwerta/p/9732540.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值