AcWing 1184. 欧拉回路
原题链接
考察:欧拉回路
思路:
模板题.主要点在删除边,邻接表删除边需要将\(road[i].ne\)改变,否则时间复杂度是\(O(m^2)\),修改后的时间复杂度是\(O(n+m)\).
关于\(dfs\)为什么用&,这是回溯时,直接得到的就是新的边,如果我们用\(h[u]\)修改,那么下次回溯时我们还是用的原来的边的ne,到时会发现下条边删除了,\(h[u]\)的值本被修改为\(-1\),最后在\(if\)判断里又被修改回来,所以时间复杂度仍然为\(O(m^2)\).
因为变成了值传递,所以后面的边变化,前面的也变了.
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100010,M = 200010;
int h[N],n,m,type,in[N],out[N],idx,ans[M<<1],cnt;
struct Road{
int to,ne,id;
bool exist;
}road[M<<1];
void add(int a,int b,int id)
{
road[idx].id = id,road[idx].exist = 1,road[idx].to = b,road[idx].ne = h[a],h[a] = idx++;
}
bool check()
{
if(type==2)
{
for(int i=1;i<=n;i++)
if(in[i]!=out[i]) return 0;
return 1;
}
for(int i=1;i<=n;i++)
if(in[i]+out[i]&1) return 0;
return 1;
}
void dfs(int u)
{
for(int& i=h[u];~i;)
{
if(!road[i].exist)
{
i = road[i].ne;
continue;
}
int v = road[i].to;
road[i].exist = 0;
if(type==1) road[i^1].exist = 0;
int id = road[i].id;
i = road[i].ne;//需要在遍历前删掉
dfs(v);
ans[++cnt] = id;
}
}
int main()
{
scanf("%d%d%d",&type,&n,&m);//t = 1无向
memset(h,-1,sizeof h);
for(int i=1;i<=m;i++)
{
int a,b; scanf("%d%d",&a,&b);
add(a,b,i);
out[a]++,in[b]++;
if(type==1) add(b,a,-i);
}
if(!check()) {puts("NO"); return 0;}
for(int i=1;i<=n;i++)
if(out[i])
{
dfs(i);
break;
}
if(cnt!=m) { puts("NO");return 0; }
puts("YES");
for(int i=cnt;i>=1;i--) printf("%d ",ans[i]);
printf("\n");
return 0;
}