欧拉回路 - 题目 - 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+行(逃