复习离散数学ing…顺手把acm中的整理发了…
欧拉道路&欧拉回路
- 无向连通图的充分必要条件
- 欧拉道路:度数为奇数的节点数=0或2
- 欧拉回路:没有奇数度的节点
- 有向连通图的充分必要条件
- 欧拉道路:所有点入度=出度 or 有一个点入度=出度+1,有一个点出度=入度+1,其余入度=出度
- 欧拉回路:所有点入度=出度
- 构造:不断删边直到成为零图,删边的原则是若只有割边走割边,否则绝不走割边
dfs(非递归版)
stack<int> stk, ans; // dfs栈和答案栈
bool vst[M]; // 记录边是否访问过
void Euler()
{
stk.push(1); // 起点
while (!stk.empty())
{
int cur = stk.top();
int i = head[cur];
while (i && vst[i])
i = edge[i].nxt;
if (i) // 找到下一条能走的路
{
stk.push(edge[i].to);
vst[i] = vst[i ^ 1] = true;
head[cur] = edge[i].nxt;
}
else
{ // 与x相连的所有边均已访问,模拟回溯过程,并记录
stk.pop();
ans.push(cur); // 记录答案
}
}
}
Hierholzers
求欧拉道路,倒序输出,字典序最小
// 将起点设为1,若找到奇数度的节点就设它为起点
void dfs(int x)
{
for (int i = 1; i <= n; i++)
if (g[x][i])
{
g[x][i]--, g[i][x]--;
dfs(i);
}
ans.push(x);
}
Fluery
stack<int> stk;
bool vst[M]; // 边是否访问过
void dfs(int u)
{
stk.push(u);
for (int i = head[u]; i; i = edge[i].nxt)
{
if (vst[i])
continue;
vst[i] = vst[i ^ 1] = true;
dfs(edge[i].to);
break;
}
}
void Fleury(int st)
{
stk.push(st);
while (!stk.empty())
{
bool flag = false;
int cur = stk.top();
stk.pop();
for (int i = head[cur]; i; i = edge[i].nxt)
if(!vst[i])
{
flag = true;
break;
}
if (!flag)
printf("%d\n", u);
else
dfs(u);
}
}