LOJ-10105(欧拉回路模板,套圈法,递归)

题目链接:传送门

思路:

(1)用邻接表存储有向图和无向图,有向图和无向图的每条边均站两个单元,无向图有正向边和反向边的区分。

(2)有向图有欧拉回路:所有点的入度=出度;

无向图有欧拉回路:所有点的度数之和是2的倍数。

(3)搜索时要从存在的点开始搜索,注意每条边站两个单位,所以i/2。

(4)搜索的结果路径必须包含所有边,如果图不连通则不行。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 200200;
struct Node{
    int to,next,val;
}edge[maxn*2];
int vis[maxn],head[maxn],IN[maxn],OUT[maxn],tot;
vector <int> ans;
void Init()
{
    memset(vis,0,sizeof(vis));
    memset(head,0,sizeof(head));
    memset(IN,0,sizeof(IN));
    memset(OUT,0,sizeof(OUT));
    tot=2;ans.clear();
}
void addedge(int u,int v,int w)
{
    edge[tot].to=v;
    edge[tot].next=head[u];
    edge[tot].val=w;
    head[u]=tot++;
}
void dfs(int u)
{
    for(int &i=head[u];i;i=edge[i].next){ //对i引用,提高速度 
        Node tmp=edge[i];
        if(!vis[i>>1]){
            vis[i>>1]=1;
            dfs(tmp.to);
            ans.push_back(tmp.val);
        }
    }
}
int main(void)
{
    int n,m,i,j,x,y,type,fg=1;
    scanf("%d%d%d",&type,&n,&m);
    Init();
    for(i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        addedge(x,y,i);
        IN[y]++;OUT[x]++;
        if(type==1) addedge(y,x,-i);
        else tot++;
    }
    
    if(type==1){  
        for(i=1;i<=n;i++)
        if((IN[i]+OUT[i])%2){
            fg=0;break;
        }
    }else{
        for(i=1;i<=n;i++)
        if(IN[i]!=OUT[i]){
            fg=0;break;
        } 
    }
    
    if(fg){
        for(i=1;i<=n;i++) //找到图中存在的点 
        if(head[i]){
            dfs(i);break;
        }
        if(ans.size()!=m) printf("NO
");
        else{
            printf("YES
");
            for(i=m-1;i>=0;i--){
                if(i!=m-1) printf(" ");
                printf("%d",ans[i]); //ans相当于栈,所以倒叙输出 
            }
        }
    }else printf("NO
");
    return 0;
}
View Code

参考文章:传送门

原文地址:https://www.cnblogs.com/2018zxy/p/10362035.html