欧拉图
无向图的欧拉路、欧拉回路、欧拉图
给定无孤立结点图G,若存在一条路,经过图中每边一次且仅一次,该条路称为欧拉路,若存在一条回路,经过图中每边一次且仅一次,该回路称为欧拉回路。具有欧拉回路的图称为欧拉图。
充要条件
无向图G具有一条欧拉路,当且仅当G是连通的,且有零个或两个奇数度结点。
无向图G具有一条欧拉回路,当且仅当G是连通的,并且所有结点度数全为偶数。
有向图的欧拉回路
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
int deg_in[N],deg_out[N],cur[N],vis[N];
struct node{
int v,id;
};
bool cmp(node a,node b){
return a.v<b.v;
}
vector<node> G[N];
stack<int> stk;
void dfs(int u){
for(int i = cur[u];i<G[u].size();i=max(i+1,cur[u])){
//注意这里cur[u]是会变化的要随时改变否则会T!!!!!!!!!
int v = G[u][i].v;
if(!vis[G[u][i].id]){
vis[G[u][i].id] = 1;
cur[u]++;
dfs(v);
}
}
stk.push(u);
}
int main(){
ios::sync_with_stdio(false); cin.tie(0);
int n,m;
cin >> n >> m;
for(int i = 1;i<=m;i++){
int u,v;
cin >> u >> v;
G[u].push_back({v,i});
deg_in[v]++;
deg_out[u]++;
}
int cnt = 0,s = 0,t = 0;
for(int i = 1;i<=n;i++){
if(deg_in[i] != deg_out[i]) cnt++;
if(deg_in[i] - deg_out[i] == 1) t = i;
if(deg_out[i] - deg_in[i] == 1) s = i;
}
if((cnt != 0) && (cnt != 2)){
cout << "No\n";
return 0;
}
if(cnt == 0){
s = t = 1;
}
if(!s||!t){
cout << "No\n";
return 0;
}
for(int i = 1;i<=n;i++) sort(G[i].begin(),G[i].end(),cmp);
dfs(s);
while(!stk.empty()){
cout << stk.top() << " ";
stk.pop();
}
cout << endl;
return 0;
}
无向图的欧拉回路
与有向是几乎相同
混合图的欧拉回路
待续
完全图的欧拉回路
图盗的题解
若对完全图进行标号,则对于任一点
x
x
x,所需连接的边为:
(
0
,
x
)
(0,x)
(0,x)
(
x
%
n
,
(
x
+
1
)
%
n
)
(x\%n,(x+1)\%n)
(x%n,(x+1)%n)差值为1
(
(
x
+
1
)
%
n
,
(
x
−
1
)
%
n
)
((x+1)\%n,(x-1)\%n)
((x+1)%n,(x−1)%n)差值为-2
(
(
x
−
1
)
%
n
,
(
x
+
2
)
%
n
)
((x-1)\%n,(x+2)\%n)
((x−1)%n,(x+2)%n)差值为3
(
(
x
+
2
)
%
n
,
(
x
−
2
)
%
n
)
((x+2)\%n,(x-2)\%n)
((x+2)%n,(x−2)%n)差值为-4
.
.
.
(
(
x
−
n
2
+
1
)
%
n
,
(
x
+
n
2
)
%
n
)
((x-\frac{n}{2}+1)\%n,(x+\frac{n}{2})\%n)
((x−2n+1)%n,(x+2n)%n)差值为n-1
(
(
x
+
n
2
)
%
n
)
,
0
)
((x+\frac{n}{2})\%n),0)
((x+2n)%n),0)
枚举所有的点
x
x
x,则可得到一条欧拉回路
Decomposition
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
vector<int> ans;
int main(){
int T,n,k;
cin >> T;
for(int i = 1;i<=T;i++){
ans.clear();
cout << "Case #"<<i<<":\n";
cin >> n >> k;
for(int i = 1;i<=n/2;i++){
ans.push_back(n);
ans.push_back(i);
int cur = i,sign = 1;
for(int j = 1;j<=n-2;j++){
cur = (cur+sign*j+n-1)%(n-1);
sign *= -1;
if(cur == 0) ans.push_back(n-1);
else ans.push_back(cur);
}
}
ans.push_back(n);
int pos = 0;
for(int i = 1;i<=k;i++){
int len;
cin >> len;
for(int j = pos;j<=pos+len;j++){
cout << ans[j] << " \n"[j==pos+len];
}
pos += len;
}
}
return 0;
}