尤拉路徑

Bubble_e發表於2024-07-19

尤拉路徑

判定定理 及 證明

有向圖

  • 尤拉路徑: 有且僅有一個 ‘入度=出度+1’ 的點和一個 ‘出度=入度+1’ 的點(起點, 終點) 或 所有點 ‘入度=出度
  • 尤拉回路:所有點入度=出度(起/終點任意)

無向圖

  • 尤拉路徑: 有且僅有兩個 度數為奇數 的點(起點, 終點) 或 所有點 ‘度數均為偶數
  • 尤拉回路:所有點度數均為偶數(起/終點任意)

證明

  • 每條邊都要走一次, 所以對於每個中間點(非起點/終點), 走進來之後都要走出去, 所以入度=出度/度數均為偶數
  • 對於起點/終點, 在開始/結束時可以只走出去/走進來, 所以入(出)度=出(入)度+1/度數為奇數

如何做到 ‘字典序最小’ ?

給 x 節點所有能到達的點排個序就行了, 哈哈哈哈

示例

  • 注意: 要確保每條邊只走一步!
#include <bits/stdc++.h>
#define int long long
#define double long double
#pragma GCC optimize(3)
using namespace std;
const int N = 1e6 + 10, INF = 1e18;

int n, m, b;
int fst[N], idg[N], odg[N], st[N];
string s[N];
vector <pair <int, int>> e[N];
vector <int> ans;

void Dfs(int x){
    // cout << x << " ";
    for(int &i = st[x]; i < e[x].size();){
        int id = e[x][i].first;
        // cout << id << "id ";
        Dfs(e[x][i++].second);
        ans.push_back(id);
    }
}

signed main(){
    // freopen("1.in", "r", stdin);
    freopen("card.in", "r", stdin);
    freopen("card.out", "w", stdout);
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);

    cin >> n >> m >> b;
    for(int i = 1; i <= n; i++){
        cin >> s[i];
    
        int ps = 0, f = 1;
        for(int j = 0; j < s[i].size(); j++){
            if(s[i][j] == '1'){
                if(!ps){
                    ps = j + 1;
                    fst[i] = j;
                    continue;
                }
                if(((j + 1) - ps) % m != 0){
                    f = 0;
                    break;
                }
                ps = j + 1;
            }
        }
        if(f == 0 || ps == 0){
            cout << "-1\n";
            return 0;
        }         

        for(int j = 0; j < s[i].size(); j++){
            if(s[i][j] == '0'){
                if((j - fst[i]) % m == 0){
                    f = 0;
                    break;
                }
            }
            if(s[i][j] != '0'){
                if((j - fst[i]) % m != 0){
                    f = 0;
                    break;
                }
            }
        }
        if(f == 0){
            cout << "-1\n";
            return 0;
        }         

        int st = ((b - fst[i]) % m + m) % m;
        int ed = ((b - fst[i] + s[i].size()) % m + m) % m;
        e[st].push_back({i, ed});
        idg[ed]++, odg[st]++;
        // cout << st << "+" << ed << "\n";
    }

    for(int i = 1; i <= n; i++){
        if(idg[i] != odg[i]){
            cout << "-1\n";
            return 0;
        }
    }
    for(int i = 0; i < m; i++){
        sort(e[i].begin(), e[i].end());
    }
    Dfs(0);
    if(ans.size() != n){
        cout << "-1\n";
        return 0;
    }
    reverse(ans.begin(), ans.end());
    for(auto i : ans){
        cout << i << " ";
    }
    cout << "\n";
}

相關文章