图论笔记
图论 笔记
一、BFS和DFS
小性质:DFS的非树边都是返祖边 BFS只有同层或者相邻层之间才有边
-
01BFS
边权是0/1的最短路
在队列里先把和起点距离为0的点压进去
然后再压距离为1的点 然后正常BFS 就可以求出起点到所有点的最短路
P1 Travel
我们考虑当前图的边权为b的子图
然后我们要在这个上面找1到n的最短路
这个子图和完全图最多差50w条边
那么每一次假设当前节点为x 我们要更新一些与他相邻的点
把这些点有序的写出来 得到一个序列 这个序列由一些区间构成
这些区间之间有一些缝隙 缝隙的个数最多为50w个 因为每一个缝隙都代表着一条不存在于图中的边
那么区间的个数最多也为50w个
所以我们需要:将一个区间中未被删除的点删除 并放入队列中
用并查集 维护一个链表链表中的点表示未被删除的点
并查集:f[i]=i 表示未被删除 f[i]=i+1表示已被删除
那么每次我们这样更新
int x=getfa(L);
while(x<=R){
fa[x]=x+1; //删除x
put x in queue; //将x放入队列中
x=getfa(x); //找到下一个未被删去的x
}
这样每个点最多被删除1次
复杂度\(O(n \alpha (n))\)
P2 Bzoj noip2016十连测 D1T3 Walk
我们考虑把每个val建一个点,假设对于一个val的位置为val+r,i->val[i]+r连一条权值为1的边,val[i]+r->i连一条权值为0的边,那么我们只要让val里面连的那些边边权为0就行了。
val里面连边暴力连显然比较蠢,我们只连二进制相差一位的val,这样传递一下就相当于连了所有边了。
那么现在我们一共\(2^{20}+200000\)个点,\(2^{20}\times 20\)条边
01最短路
复杂度和bfs一样
二、最短路和最短路树
-
Floyd
-
SPFA
-
Dijkstra
-
最短路图/树
如果dis(u)+w(u,v)=dis(v),那么在(u,v)之间连一条边 构成最短路图
他的一棵生成树称为最短路树
P1 NOIP2017逛公园
先做出最短路图 找到拓扑序
令\(f[i][j]\)表示当前走到\(i\),当前的距离-起点到\(i\)的最短路=\(j\)的方案数
\(f[i][j]->f[k][j]\) 边\((i,k)\)在最短路图中
\(f[i][j]->f[k][j+(w[i][k]-(dis[k]-dis[i]))]\) 边\((i,k)\)不再最短路图中
然后按照拓扑序更新就好了
P2
跳过了
P3 BZOJ3073
首先构图 对于区间\([a,b]\)和区间\([c,d]\)
我们新建两个节点\(x,y\)
然后把\([a,b]\)的点连到\(x\),\([c,d]\)的点连到\(y\)
然后跑最短路 复杂度\(O(nm)\)
线段数优化建边 可以把边数做到\(m \log n +n\)
复杂度 \(O(m\log n)\)
P4 CF 464E
跳过了
P5 Gym - 100959C Jump
首先建图显然 每个点向他对称得到的\(n\)个点连边
但是我们要回答\(Q\)组询问 每一组询问都得跑一边最短路 设边数为\(m=10000n\) 那么复杂度是\(O(Qm)\) 爆炸了
只能做一次最短路
发现 从\(S\)到\(T\) 等价于 从\(0\)到\(T-S\)或\(T+S\)
那么只要做从0出发的 到每个点跳了奇数次和偶数次的最短路即可
复杂度\(O(m+Q)\)
Tarjan
在一个有向图G里,设两个点 a b 发现,由a有一条路可以走到b,由b 又有一条路可以走到a,我们就叫这两个顶点(a,b)强连通。
-
强连通分量:在一个有向图G中,有一个子图,这个子图每2个点都满 足强连通,我们就叫这个子图叫做 强连通分量。
-
Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索 树中的一棵子树。搜索时,把当前搜索树中未处理的节点加入一个堆 栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。
•Tarjan算法中,有如下定义。
•DFN[ i ] : 在DFS中该节点被搜索的次序(时间戳)
•LOW[ i ] : 为i或i的子树能够追溯到的最早的栈中节点的次序号
•当DFN[ i ]==LOW[ i ]时,为i或i的子树可以构成一个强连通分量
-
桥与割点
•怎么判断一个点到父亲的边是桥?
Low[x]>=dfn[x]
•怎么判断一个点是割点?
x存在某个儿子y,low[y]>=dfn[x]
P1 矿场搭建
经典题
题解略