欧拉回路 - 题目 - 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=;
a[i^].nod=;
d[x]--;
d[a[i].e]--;
dfs(a[i].e);
st.push(x);
}
return;
}

肥肠标准的Hierholzer嘛。

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

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

      当前弧优化

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

eg:


...

在这种情况下,我们每一次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=;
a[i^].nod=;
d[x]--;
d[a[i].e]--;
dfs(a[i].e);
st[++tos]=f;//换成了数组模拟的栈
}
}
return;
}

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

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

 /*
ID 题目 提交者 结果 用时 内存 语言 文件大小 提交时间 测评时间
#288775 #117. 欧拉回路 qwerta 100 534ms 14912kb C++ 3.0kb 2018-09-30 16:29:45 2018-09-30 16:29:47
*/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<stack>
using namespace std;
#define R register
const int MAXN=1e5+;
const int MAXM=2e5+;
struct emm{
int e,f,nod;
}a[*MAXM];
int h[MAXN];
int tot=;
inline void con(int x,int y,int k)
{
a[++tot].f=h[x];
h[x]=tot;
a[tot].e=y;
a[tot].nod=k;
return;
}
int d[MAXN];
int st[*MAXM];
int tos=;
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;
if(a[i].nod)
{
int f=a[i].nod;
a[i].nod=;
a[i^].nod=;
d[x]--;
d[a[i].e]--;
dfs(a[i].e);
st[++tos]=f;
}
}
return;
}
int tim=;
void dfss(int x)
{
//cout<<tos<<endl;
//for(R int i=h[x];i;i=a[i].f)
while(h[x])
{
int i=h[x];
h[x]=a[i].f;
if(a[i].nod)
{
int f=a[i].nod;
a[i].nod=;
d[x]--;
d[a[i].e]--;
dfss(a[i].e);
st[++tos]=f;
}
}
return;
}
int fa[MAXN];
inline int fifa(int x)
{
if(fa[x]==x)return x;
return fa[x]=fifa(fa[x]);
}
int rd[MAXN];
int cd[MAXN];
int main()
{
//freopen("a.in","r",stdin);
int t;
scanf("%d",&t);
if(t==)
{
int n,m;
scanf("%d%d",&n,&m);
for(R int i=;i<=n;++i)
fa[i]=i;
for(R int i=;i<=m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
con(u,v,i);
con(v,u,-i);
d[u]++;
d[v]++;
fa[fifa(u)]=fifa(v);
}
//
for(R int i=;i<=n;++i)
if(d[i]%==){cout<<"NO";return ;}
int tag=;
for(R int i=;i<=n;++i)
if(d[i])
{
if(!tag)tag=fifa(i);
else if(fifa(i)!=tag){cout<<"NO";return ;}
}
//
int s=-;
for(R int i=;i<=n;++i)
if(d[i]){s=i;break;}
dfs(s);
cout<<"YES"<<endl;
while(tos)
{
printf("%d ",st[tos]);
--tos;
}
}
else
{
int n,m;
scanf("%d%d",&n,&m);
for(R int i=;i<=n;++i)
fa[i]=i;
for(R int i=;i<=m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
con(u,v,i);
cd[u]++;
rd[v]++;
fa[fifa(u)]=fifa(v);
}
//
for(R int i=;i<=n;++i)
if(rd[i]!=cd[i]){cout<<"NO";return ;}
int tag=;
for(R int i=;i<=n;++i)
if(rd[i]||cd[i])
{
if(!tag)tag=fifa(i);
else if(fifa(i)!=tag){cout<<"NO";return ;}
}
//
int s=;
for(R int i=;i<=n;++i)
if(rd[i]||cd[i]){s=i;break;}
dfss(s);
cout<<"YES"<<endl;
while(tos)
{
printf("%d ",st[tos]);
--tos;
}
}
return ;
}
//其实删欧拉通路和那些调试之前有200+行(逃

「UOJ#117」 欧拉回路的更多相关文章

  1. 【UOJ 117】欧拉回路

    #117. 欧拉回路 有一天一位灵魂画师画了一张图,现在要你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次. 一共两个子任务: 这张图是无向图.(50分) 输入格式 第一行一个整数 t, ...

  2. 「UOJ 514」通用测评号(生成函数)

    首先,题目中的过程可以看作:每次选择任意一个燃料仓,给它装填 \(1\) 单位的燃料,如果此时恰好 "填满" 了它,就给答案 \(+1\). 考虑 \(n\) 号燃料仓填满的概率, ...

  3. Solution -「UNR #5」「UOJ #671」诡异操作

    \(\mathcal{Desciprtion}\)   Link.   给定序列 \(\{a_n\}\),支持 \(q\) 次操作: 给定 \(l,r,v\),\(\forall i\in[l,r], ...

  4. Solution -「UOJ #46」玄学

    \(\mathcal{Description}\)   Link.   给定序列 \(\{a_n\}\) 和 \(q\) 次操作,操作内容如下: 给出 \(l,r,k,b\),声明一个修改方案,表示 ...

  5. Solution -「JOISC 2020」「UOJ #509」迷路的猫

    \(\mathcal{Decription}\)   Link.   这是一道通信题.   给定一个 \(n\) 个点 \(m\) 条边的连通无向图与两个限制 \(A,B\).   程序 Anthon ...

  6. Solution -「UR #21」「UOJ #632」挑战最大团

    \(\mathcal{Description}\)   Link.   对于简单无向图 \(G=(V,E)\),定义它是"优美"的,当且仅当 \[\forall\{a,b,c,d\ ...

  7. Solution -「UOJ #87」mx 的仙人掌

    \(\mathcal{Description}\)   Link.   给出含 \(n\) 个结点 \(m\) 条边的仙人掌图.\(q\) 次询问,每次询问给出一个点集 \(S\),求 \(S\) 内 ...

  8. Solution -「UR #2」「UOJ #32」跳蚤公路

    \(\mathcal{Description}\)   Link.   给定一个 \(n\) 个点 \(m\) 条边的带权有向图,每条边还有属性 \(s\in\{-1,0,1\}\).对于每个 \(u ...

  9. Solution -「UOJ #450」复读机

    \(\mathcal{Description}\)   Link.   求从 \(m\) 种颜色,每种颜色无限多的小球里选 \(n\) 个构成排列,使得每种颜色出现次数为 \(d\) 的倍数的排列方案 ...

随机推荐

  1. xshell登陆腾讯云服务器

    2016-12-11   00:17:36 前段时间在同学的介绍下关注了一下腾讯云:然后里面有学生优惠可以拿到免费的域名和云服务器.所以感兴趣就实验了一下,今天中午抢到了“1元特惠的学生包”,里面有免 ...

  2. Git以及github的使用方法(一)安装并设置git用户

    最早Git是在Linux上开发的,很长一段时间内,Git也只能在Linux和Unix系统上跑.不过,慢慢地有人把它移植到了Windows上.现在,Git可以在Linux.Unix.Mac和Window ...

  3. Android_自己定义切换控件SwitchView

    1.示意图 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemltbzIwMTM=/font/5a6L5L2T/fontsize/400/fill/I0JB ...

  4. Ffmpeg 实现文件切割

    文件切割是一项很常见的基本功能,通过Ffmpeg可以很容易实现这项功能. 首先介绍下基本原理,文件切割说白了就过滤掉文件的部分音视频包,按照什么规则过滤呢? 答案是时间戳.文件中每个视频及音频包都有时 ...

  5. 读《疯狂Java讲义》笔记总结三

    1.初始化块 实际上初始化块是一个假象,使用javac命令编译Java类后,该Java类中的初始化块会消失--初始化块中代码会被 "还原" 到每一个构造器中,且位于构造器全部代码的 ...

  6. 如何成为一个Linux内核开发者

    你想知道如何成为一个Linux内核开发者么?或者你的老板告诉你,“去为这个设备写一个Linux驱动.“这篇文档的目的,就是通过描述你需要 经历的过程和提示你如何和社区一起工作,来教给你为达到这些目的所 ...

  7. 当CSDN携手Markdown

    当CSDN携手Markdown Tags: CSDN Markdown 当CSDN携手Markdown Markdown CSDN-Markdown 也不知道是不是基于 Github 崛起的因素,Ma ...

  8. SSH实现在WIN7系统下访问虚拟机中的Linux系统

    使用的是centos6.4进行练习的,安装的是vmware8虚拟机.以下是总结的一些步骤: 一.确保vmware使用NAT的连接方式,如做地址.端口映射 首先查看vmware的中网络连接的一些方式:E ...

  9. Linux 系统编程中环境变量的使用

    前言 在 UNIX Like 系统中,存有各类系统/应用程序的环境变量,可通过修改之改变系统/应用程序的执行效果:除此之外,用户还可以定义自己的环境变量,供自己写的程序使用.本文将说明如何在程序中设置 ...

  10. 模式匹配之常见匹配算法---SIFT/SURF、haar特征、广义hough变换的特性对比分析

    识别算法概述: SIFT/SURF基于灰度图, 一.首先建立图像金字塔,形成三维的图像空间,通过Hessian矩阵获取每一层的局部极大值,然后进行在极值点周围26个点进行NMS,从而得到粗略的特征点, ...