欧拉回路模板
模板题:欧拉回路(含有向图和无向图)
未优化版:复杂度又可能会超过O(m),原因是把当前边删掉后,只有子节点会受影响,而它的父节点会继续遍历被删去的边,例如在1个点,很多自环的例子中会被卡
#include<bits/stdc++.h>
#define LL long long
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
int t;
const int N = 1e5 + 10, M = 4e5 + 10;
int h[N], e[M], ne[M], idx;
void add(int a, int b) {
ne[idx] = h[a], e[idx] = b, h[a] = idx++;
}
int n, m;
int din[N], dout[N];
bool st[M];//每条边是否被访问过
int cnt;//一共访问了几条边
int res[M / 2];//欧拉回路dfs后保存的是逆序
void dfs(int u) {
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (st[i]) {
h[u] = ne[i];
continue;
}
h[u] = ne[i];
st[i] = true;
if (t == 1)st[i ^ 1] = true;
dfs(j);//先dfs所有子节点,再加入当前的节点到res数组中
cnt++;
if (t == 1) {
if (i & 1) {
res[cnt] = -(i / 2 + 1);
}
else {
res[cnt] = i / 2 + 1;
}
}
else {
res[cnt] = i+1;
}
}
}
int main() {
freopen("in.in", "r", stdin);
memset(h, -1, sizeof h);
cin >> t;
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int a, b;
cin >> a >> b;
add(a, b);
dout[a]++, din[b]++;
if (t == 1)add(b, a);
}
if (t == 1) {
for(int i=1;i<=n;i++)
if ((din[i] + dout[i]) & 1) {//这里是为了取巧,把无向图“所有节点的度是偶数”,变成“入度”和“出度”相加是偶数
puts("NO");
return 0;
}
}
else {
for (int i = 1; i <= n; i++) {
if (din[i] != dout[i]) {
puts("NO");
return 0;
}
}
}
for (int i = 1; i <= n; i++) {
if (h[i] != -1) {//注意是要选第一个不是孤立点的点
dfs(i);
break;
}
}
if (cnt < m)puts("NO");
else {
puts("YES");
for (int i = m; i; i--) {
cout << res[i] << " ";
}
}
}
优化做法:
把i保存为h[u]的地址,在边被删除时,它的父节点的i会自动变成当前未被访问过的边,而不会再重复遍历同一条边,可以把复杂度优化到准确的O(m)
#include<bits/stdc++.h>
#define LL long long
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
int t;
const int N = 1e5 + 10, M = 4e5 + 10;
int h[N], e[M], ne[M], idx;
void add(int a, int b) {
ne[idx] = h[a], e[idx] = b, h[a] = idx++;
}
int n, m;
int din[N], dout[N];
bool st[M];
int cnt;
int res[M / 2];
void dfs(int u) {
for (int& i = h[u]; ~i; ) {//&i=h[u]
int j = e[i];
if (st[i]) {
i = ne[i];
continue;
}
st[i] = true;
if (t == 1)st[i ^ 1] = true;
int tmp_ans;
if (t == 1) {
if (i & 1) {
tmp_ans = -(i / 2 + 1);
}
else {
tmp_ans = i / 2 + 1;
}
}
else {
tmp_ans = i + 1;
}
i = ne[i];
dfs(j);
res[++cnt]=tmp_ans;
}
}
int main() {
freopen("in.in", "r", stdin);
memset(h, -1, sizeof h);
cin >> t;
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int a, b;
cin >> a >> b;
add(a, b);
dout[a]++, din[b]++;
if (t == 1)add(b, a);
}
if (t == 1) {
for(int i=1;i<=n;i++)
if ((din[i] + dout[i]) & 1) {
puts("NO");
return 0;
}
}
else {
for (int i = 1; i <= n; i++) {
if (din[i] != dout[i]) {
puts("NO");
return 0;
}
}
}
for (int i = 1; i <= n; i++) {
if (h[i] != -1) {
dfs(i);
break;
}
}
if (cnt < m)puts("NO");
else {
puts("YES");
for (int i = m; i; i--) {
cout << res[i] << " ";
}
}
}
浙公网安备 33010602011771号