哈密路回路
如果一个总点数至少为3的简单图G满足:G的任意两个点u和v度数之和至少为n,即deg(u)+deg(v)≥n,那么G必然有哈密顿回路。
可以n^2构造
看这篇博客
欧拉回路
中国邮差问题
邮差叔叔走访每条大街小巷,让家家户户都收到信。
给定一张图,找出一条环状路线(起点和终点相同),图上每条边至少经过一次,并且距离最短。
如果求路径,则匹配的时候少匹配一对点
无向图演算法
http://web.mit.edu/urban_or_book/www/book/chapter6/6.4.4.html
- 先判断整张图是否连通,否则无解。
- 找出图上所有奇点,一定是偶数个。
- 找出所有奇点点对之间的最短路径长度。
- 把这些奇点做最小权匹配,权重采用刚才算的最短路径长度。
- 把匹配边加在原图上,再找欧拉环,即得中国邮差路径之权重。
- 将匹配边改成其代表的最短路径,即得中国邮差路径。
时间复杂度为六项步骤总和。各条匹配边所代表的最短路径,绝对不会重叠。
有向图演算法
- 先判断整张图是否为一个强连通分量,否则无解。
- 找出图上所有出边数不等于入边数的点。
- 于上述找到的点,找出所有点对之间的最短路径长度。
- 令d(x)为x点出边与入边的数量差。
出边多于入边的点x,建立d(x)份,放在X侧。
出边少于入边的点y,建立d(y)份,放在Y侧。
最后建立X侧到Y侧的边,权重采用刚才算的最短路径长度。
算最小权二分匹配。- 合理的做法是建立最小权最大流模型:
把出边多于入边的点x,放在X侧。拉一条源点到x点的边,权重为零,容量为d(x)。
把出边少于入边的点y,放在Y侧。拉一条y点到汇点的边,权重为零,容量为d(y)。
最后建立X侧到Y侧的边,权重采用刚才算的最短路径长度,容量为无限大。
算最小权最大流。- 把匹配边加在原图上,再找欧拉环,即得中国邮差路径之权重。
- 将匹配边改成其代表的最短路径,即得中国邮差路径。<
欧拉回路新的求法:Hierholzer’s algorithm
大概是先找从v出发回到v的一个回路,然后再基于当前回路增广。每次加入一个圈。保证每次求完都是一个圈。
要用双向链表实现,比较麻烦。
有个好处就是不会像直接dfs那样留出不完整的环,在动态开点的欧拉回路问题中有点用
一些例题
对每一个联通块,入度大的向出度大的点连边,直到出入度相等。最后在欧拉回路上删除一条边即得欧拉路径
不求方案不需要真正连边
总结
欧拉回路经常与边的定向,要求遍历所有序列等问题有关
常用的思路是将哈密顿回路问题转化为欧拉回路,从而变得可解
图的计数技巧
对度数根号n分治
统计三元环、四元环个数:O(m* sqrt(m))
udpate
直接把边按照度数从小到大定向。那么每个点的出边显然只有sqrt(m)条
三元环:
直接标记所有出边,才枚举出边的出边统计标记
四元环:
在度数最大处统计
枚举其对面的点,走两步,每走到一次该点统计答案并把标记+1
四条边的联通块:自己分类讨论算重的情况,但要注意技巧,不能把讨论情况分得太多
正戊烷 + 新戊烷 + 异戊烷 - (三元环 + 边和三元环)* 3 - 四元环 * 3
#include<bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define rvc(i,S) for(register int i = 0 ; i < (int)S.size() ; i++)
#define rvcd(i,S) for(register int i = ((int)S.size()) - 1 ; i >= 0 ; i--)
#define fore(i,x)for (register int i = head[x] ; i ; i = e[i].next)
#define forup(i,l,r) for (register int i = l ; i <= r ; i += lowbit(i))
#define fordown(i,id) for (register int i = id ; i ; i -= lowbit(i))
#define pb push_back
#define prev prev_
#define stack stack_
#define mp make_pair
#define fi first
#define se second
#define lowbit(x) ((x)&(-(x)))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int,int> pr;
const int maxn = 2e5 + 10;
const int mod = 1e9 + 7;
const int inv2 = (mod + 1) >> 1;
int n,m,deg[maxn],pos[maxn],order[maxn],vis[maxn];
vector <int> adj[maxn],graph[maxn];
//====================================basic operation===============================
inline void add(int &x, int y) {
x += y;
if (x >= mod) {
x -= mod;
}
}
inline void sub(int &x, int y) {
x -= y;
if (x < 0) {
x += mod;
}
}
inline int mul(int x, int y) {
return (int) ((long long) x * y % mod);
}
inline int power(int x, int y) {
int res = 1;
while (y) {
if (y & 1) {
res = mul(res, x);
}
x = mul(x, x);
y >>= 1;
}
return res;
}
//====================================================================&#