P7771 【模板】尤拉路徑

黑屿白發表於2024-04-06

原題連結

題解

鏈式前向星版本的尤拉回路dfs

void dfs(int u){
    for (int i=head[u];i>0;i=head[u]){
        head[u]=Next[i];   //走過的路直接跳過
        dfs(to[i]);
    }
    que[l++]=u;
}

接下來的難點是如何字典序搜尋。我們在dfs的時候直接讓走字典序最小的邊即可;而由於鏈式前向星是從後往前列舉的,我們需要對所有的邊進行排序。

bool cmp(Node a,Node b){
    if (a.u!=b.u) return a.u<b.u;
    return a.v>b.v;  //保證每次列舉都是字典序最小的邊
}

code

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
const int M=2e5+5;
int head[N],Next[M],to[M],in[N],out[N];
struct Node{
    int u,v;
};
Node a[M];
bool cmp(Node a,Node b){
    if (a.u!=b.u) return a.u<b.u;
    return a.v>b.v;
}
int cnt=1,l=0;
int que[M];
void build(int i){
    Next[cnt]=head[a[i].u];
    to[cnt]=a[i].v;
    head[a[i].u]=cnt++;
}
void dfs(int u){
    for (int i=head[u];i>0;i=head[u]){
        head[u]=Next[i];
//        cout<<u<<" "<<to[i]<<endl;
        dfs(to[i]);
    }
    que[l++]=u;
}
int main(){
    int n,m;
    cin>>n>>m;
    for (int i=1;i<=m;i++){
        cin>>a[i].u>>a[i].v;
        in[a[i].v]++;
        out[a[i].u]++;
    }
    int n1=0,n2=0,start=1,end=n;
    for (int i=1;i<=n;i++){
        if (in[i]-out[i]==1){
            n1++;
            end=i;
            continue;
        }
        if (out[i]-in[i]==1){
            n2++;
            start=i;
            continue;
        }
        if (in[i]!=out[i]){
            cout<<"No\n";
            return 0;
        }
    }
    if ((n1==0 && n2==0) || (n1==1 && n2==1)){
        sort(a+1,a+m+1,cmp);
//        for (int i=1;i<=m;i++) cout<<a[i].u<<" "<<a[i].v<<endl;
        for (int i=1;i<=m;i++) build(i);
        dfs(start);
        while (l){
            if (l) cout<<que[--l]<<" ";
            else cout<<que[--l];
        }
    }
    else cout<<"No\n";
    return 0;
}