DP&图论 DAY 4 下午
后天考试不考二分图,双联通
考拓扑排序
图论
图的基本模型
边:
有向边构成有向图
无向边构成无向图
权值:
1.无权
2.点权
3.边权
4.负权(dij不可以跑)
环:
1.
2.重边
3.有向无环图DAG
路径:
1.简单路径:不经过重复的点 1-->2-->3
不简单路径:经过重复点 1-->2-->3-->1-->4
2.连通,具有传递性
图:
1.树:n个点,n-1条边的无环连通图
2.完全图:一个无向图,图中任意两点之间都有一条连边
3.竞赛图:完全图中的每一条边确定一个方向
4.基环树
5.仙人掌:不是树,图里可以成环,每一条边,要么不在环上,要么只属于一个环
图的输入方式
图的存储方式
图的遍历方法
拓扑排序基于BFS
三种遍历顺序
1.前序遍历 中左右
2.中序遍历 左中右
3.后序遍历 左右中
QUS:给前序中序,写后序
前序第一个就是根,找到在中序的位置,递归
例题1:
给定一个有向图,边权为 1 或 2,求单源最短路。
>Solution
稍微改写一下 BFS 即可。
# 创建三个集合, Q0 表示当前层, Q1 表示距离为 1 的层,
Q2 表示距离为 2 的层,初始 Q0 = {s}, Q1= ∅, Q2= ∅
# 依次取出 Q0 中的点,将其邻点放入对应的 Q1 或 Q2 中
# Q0 = Q1, Q1 = Q2, Q2 = ∅
注意一个点可能和当前层既有长度为 1 的边,又有长度为 2 的
边,应当将其加入 Q1 而非 Q2。
bfs:
建立一个辅助点
每个权是2的边u→v ,都改成 u→辅助点,辅助点→v ,权为1 ,这样边权就都是1
例题2
给出一个有向图和起点 s,对每条边 < u, v > 回答,如果删去这
条边,从 s 到 v 的最短路长度是否会改变。
>Solution
# BFS 求出从 s 出发的单源最短路
# 建立最短路图,即保留满足 dv = du + 1 的边 < u, v >
#如果询问的边不在最短路图中,那么删掉不改变
# 在最短路图上,如果 v 的入度为 1,则该入边是从 s 到 v
的必经边,若删去则 v 的最短路长度会改变
# 在最短路图上,如果 v 的入度大于 1,则删去任何一条入
边, v 的最短路长度都不会改变
拓扑排序
有向无环图的拓扑排序即将所有顶点排为线性序列,使得对于任意的 < u, v >∈ E,都有 u 在线性序列中出现于 v 之前。
有向图中如果有环,则一定不存在拓扑排序;如果没有环,则一定存在拓扑排序。
# 选取一个入度为 0 的点记为 u
# 将 u 添加到线性序列末端
# 删去所有 u 的出边
# 重复上述步骤直到所有点都被加入序列
void topsort() { queue<int> q; for(int i=1;i<=n;i++) if(!in[i]) q.push(i); while(!q.empty()) { int u=q.front(); q.pop(); ans[++cnt]=u; for(int i=head[u];i;i=edge[i].nxt) { int y=edge[i].v; in[y]--; if(!in[y]) q.push(y); } } if(cnt!=n) printf("you fu huan!!!"); }
// Tuo Pu Pai Xu void toposort() { static int que[mxn]; int l = 0, r = 0; for (int i = 1; i <= n; ++i) if (cnt[i] == 0) que[r++] = i; while (l != r) { int u = que[l++]; for (int i = hd[u], v; i; i = nt[i]) if (--cnt[v = to[i]] == 0) que[r++] = v; } }