DP&图论  DAY 4  下午

后天考试不考二分图,双联通

考拓扑排序

 

图论

DP&图论  DAY 4  下午图论

 

 

图的基本模型

DP&图论  DAY 4  下午图论

DP&图论  DAY 4  下午图论

 

 

边:

有向边构成有向图

无向边构成无向图

DP&图论  DAY 4  下午图论

 

 

权值:

1.无权

2.点权

3.边权

4.负权(dij不可以跑)

 

环:

1.DP&图论  DAY 4  下午图论

2.重边

3.有向无环图DAG

 

路径:

1.简单路径:不经过重复的点  1-->2-->3

   不简单路径:经过重复点  1-->2-->3-->1-->4

2.连通,具有传递性

 

图:

1.树:n个点,n-1条边的无环连通图

2.完全图:一个无向图,图中任意两点之间都有一条连边

3.竞赛图:完全图中的每一条边确定一个方向

4.基环树

5.仙人掌:不是树,图里可以成环,每一条边,要么不在环上,要么只属于一个环

DP&图论  DAY 4  下午图论

 

 

 

图的输入方式

DP&图论  DAY 4  下午图论

 

 

 图的存储方式

 DP&图论  DAY 4  下午图论

 

 DP&图论  DAY 4  下午图论

 

 

 图的遍历方法

 DP&图论  DAY 4  下午图论

 

DP&图论  DAY 4  下午图论

 

DP&图论  DAY 4  下午图论

 

 拓扑排序基于BFS

 DP&图论  DAY 4  下午图论

 

三种遍历顺序

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

bfs就行了

 

 

例题2

给出一个有向图和起点 s,对每条边 < u, v > 回答,如果删去这
条边,从 s v 的最短路长度是否会改变。

>Solution

# BFS 求出从 s 出发的单源最短路
# 建立最短路图,即保留满足 dv du + 1 的边 < u, v

#如果询问的边不在最短路图中,那么删掉不改变
# 在最短路图上,如果 v 的入度为 1,则该入边是从 s v
的必经边,若删去则 v 的最短路长度会改变
# 在最短路图上,如果 v 的入度大于 1,则删去任何一条入
边, v 的最短路长度都不会改变

 

 

拓扑排序

有向无环图的拓扑排序即将所有顶点排为线性序列,使得对于任意的 u>∈ E,都有 在线性序列中出现于 之前。
有向图中如果有环,则一定不存在拓扑排序;如果没有环,则一定存在拓扑排序。 

# 选取一个入度为 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;
    }
}
YouSiki's Code

相关文章: