1.【定義】
歐拉路我們將其稱為是一個圖中從某一節點 \(S\) 出發,恰好經過圖中每條邊各一次,但是可以重復經過圖中節點的路。
歐拉回路就是指就是從某點 \(S\) 出發最后仍回到 \(S\) 的歐拉路。
存在歐拉路的圖被稱為歐拉圖。
存在歐拉路但是不存在歐拉回路的圖叫做半歐拉圖。
2.【判定】
【歐拉圖的判定】
一張無向圖為歐拉圖,僅當無向圖連通,並且每個節點的度數為偶數。
證明: 等價於判定是否存在歐拉回路,而每條邊都要經過,然后回到最開始等價於是進行出去與回來的反復操作,所以判定正確。
【歐拉路存在性判定】
一張無向圖中存在歐拉路,僅當無向圖連通,並且恰好只有兩個節點 \(S\) 和 \(T\) 的度數為奇數其他均為偶數。
證明: 等價於是不在回到起點的歐拉回路,聯合上面證明所以顯然。
【半歐拉圖的判定】
一張無向圖是半歐拉圖當且僅當這個圖是連通的,並且恰好有 \(2\) 個奇度數節點。
證明: 等價於判斷處在歐拉路。
【有向圖歐拉圖判定】
所有點屬於一個強連通分量且每個頂點的入度和出度相同。
【有向圖半歐拉圖判定】
將所有有向邊變成無向邊時,所有點屬於一個強連通分量。
最多只有一個頂點的出度與入度差為 \(1\) 。
最多只有一個頂點的入度與出度差為 \(1\) 。
所有其他頂點的入度與出度相同。
3.【題目】
P7771 【模板】歐拉路徑
求有向圖字典序最小的歐拉路徑。
模板歐拉路,按照上面的方法模擬就是了。
const int N = 3e5;
int n, m, in[N], out[N], vis[N], ans[N], num, cur[N];
vector<int> ver[N];
void dfs(int x) {
for (int i = cur[x]; i < ver[x].size(); i = cur[x]) {
cur[x] = i + 1;
dfs(ver[x][i]);
}
ans[++num] = x;
}
signed main() {
n = read(), m = read();
for (int i = 1; i <= m; i++) {
int a = read(), b = read();
ver[a].push_back(b);
in[b]++;
out[a]++;
}
for (int i = 1; i <= n; i++)
sort(ver[i].begin(), ver[i].end());
int pd = 0, st = 1, en = 0;
for (int i = 1; i <= n; i++) {
if (in[i] == out[i])
continue;
else {
if (in[i] + 1 == out[i]) {
if (pd && st) {
printf("No\n");
return 0;
} else
st = i;
}
if (out[i] + 1 == in[i]) {
if (en) {
printf("No\n");
return 0;
} else
en = i;
}
pd = 1;
}
}
dfs(st);
for (int i = num; i; i--)
printf("%lld ", ans[i]);
printf("\n");
return 0;
}