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;
}
posted @ 2021-07-15 21:35  acmloser  阅读(50)  评论(0编辑  收藏  举报