LOJ 10105. 欧拉回路

补题地址
欧拉回路模板题。
思路
这个的关键是:当我们用链式前向星存图时,读第 i 条边(x, y)
如果是无向边:(x,y) 边存的编号是(i - 1) * 2,反向边 (y,x) 边的编号是(i - 1) * 2 + 1。
如果是单向边:(x,y) 边的编号是 i - 1。

所以如果是有向图,&i=head[u]是引用 i = head[u], 来达到修改 head[u] 的目的, 这样走过的边不会再处理,是弧优化。
如果是无向图,把vis[i ^ 1]标记为1,这样就不会再访问了,并且有弧优化,所以可以保证不会把走过的边再走一遍。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
#include<string>
#include<bitset>
#include<fstream>
using namespace std;
#define rep(i, a, n) for(int i = a; i <= n; ++ i);
#define per(i, a, n) for(int i = n; i >= a; -- i);
typedef long long ll;
typedef pair<int,int> PII;
const int N = 1e6 + 105;
const int mod = 1e9 + 7;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f; 
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b & 1) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
// bool cmp(int a, int b){return a > b;}
//


int n, m, type;
int head[N], cnt = 0;
int to[N << 1], nxt[N << 1];
int in[N], out[N];
bool vis[N];
int res[N], tot = 0;

void add(int u, int v){
    to[cnt] = v, nxt[cnt] = head[u], head[u] = cnt ++;
}

void dfs(int u){
    for(int &i = head[u]; i != -1; ){
        if(vis[i]){
            i = nxt[i];
            continue;
        }
        
        if(type == 1) vis[i ^ 1] = 1;
        int tp;
        if(type == 1){
            tp = i / 2  + 1;  
            if(i & 1) tp = -tp;
        }
        else tp = i + 1;
        
        int v = to[i];
        i = nxt[i];
        dfs(v);
        
        res[++ tot] = tp;
    }
}

int main()
{
    scanf("%d%d%d",&type,&n,&m);
    cnt = 0;
    memset(head, -1, sizeof(head));
    for(int i = 1; i <= m; ++ i){
        int x, y; scanf("%d%d",&x,&y);
        add(x, y);
        if(type == 1) add(y, x);
        in[y] ++, out[x] ++;
    }
    
    if(type == 1){
        for(int i = 1; i <= n; ++ i)
            if((in[i] + out[i]) & 1){
                printf("NO
");
                return 0;
            }
    }
    else{
        for(int i = 1; i <= n; ++ i)
            if(in[i] != out[i]){
                printf("NO
");
                return 0;
            }
    }
    
    for(int i = 1; i <= n; ++ i){
        if(head[i] != -1){
            dfs(i); break;
        }
    }
    
    if(tot < m) printf("NO
");
    else{
        printf("YES
");
        for(int i = tot; i >= 1; -- i) printf("%d ",res[i]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/A-sc/p/13752446.html