图论专题笔记

写在前面

目录

一、最短路

二、最小生成树

三、树的直径与最近公共祖先

四、基环树

五、负环与差分约束

六、Tarjan算法与无向图连通性

七、Tarjan算法与有向图连通性

八、二分图的匹配

九、二分图的覆盖与独立集

十、网络流初步

题目完成进度

0/10

 


 

一、最短路

单源最短路径

以下皆默认1号节点为起点

$dijkstra$算法

算法流程如下:

1.初始化$dist[1]=0$,其余节点的$dist$值为无穷大

2.找出一个未被标记的,$dist[x]$最小的节点$x$,然后标记节点$x$

3.扫描节点$x$的所有出边$(x,y,z)$,$dist[y]=min(dist[y],dist[x]+z)$

4.重复2、3两步,直到所有节点都被标记

$dijkstra$算法基于贪心思想,只适用于所有边的长度都是非负数的边

算法复杂度为$O(n^2)$,如果用二叉堆对$dist$数组进行维护,用$O(log\ n)$的时间获取最小值并从堆中删除,用$O(log\ n)$的时间执行一条边的扩展和更新,最终可在$O(mlog\ n)$的时间内实现$dijkstra$算法。

$Bellman-Ford$算法和$SPFA$算法

若对于图中的某一条边$(x,y,z)$,有$dist[y]\le dist[x]+z$,则称该边满足三角形不等式。若所有边都满足三角形不等式,则$dist$数组就是所求最短路。

首先说一下基于迭代思想的$Bellman-Ford$算法,算法流程如下:

1.扫描所有边$(x,y,z)$,若$dist[y]\le dist[x]+z$,则用$dist[x]+z$更新$dist[y]$

2.重复上述步骤,知道没有更新操作发生。

时间复杂度为$O(nm)$

$SPFA$算法实际上是“队列优化的$Bellman-Ford$算法”,算法流程如下:

1.建立一个队列,最初队列中只含有起点1

2.取出队头节点$x$,扫描所有出边$(x,y,z)$,若可以更新则更新,同时如果$y$不在队列中,则把$y$入队

3.重复第2步,直到队列为空

在任意时刻,队列中都保存了待扩展的节点,每次入队相当于完成了一次$dist$数组的更新操作,使其满足三角形不等式。一个节点可能会入队、出队多次。最终,图中节点收敛到全部满足三角形不等式的状态。这个队列避免了$Bellman-Ford$算法中对不需要扩展的节点的冗余扫描,在稀疏图上运行效率较高,为$O(km)$级别,其中$k$是一个小常数。但在稠密图或特殊构造的网格图上,该算法仍可能退化为$O(nm)$。(所以$SPFA$容易被卡)

$Bellman-Ford$算法和$SPFA$算法在有长度为负数的边的图中也能正常工作,只不过时间复杂度会进一步增加。有一个$SLF$优化策略,基于双端队列的思想,在每次更新$dist[y]$之后,把$dist[y]$与当前队头节点(是$x$出队后,队头的那个节点)的$dist$值进行比较。若$dist[y]$更小,则从队头把$y$入队,否则仍从队尾入队。

如果图中不存在长度为负数的边,那么类似于优先队列$bfs$,我们也可以用二叉堆对$SPFA$算法进行优化,堆代替了一般的队列,用于保存待扩展的节点,每次取出“当前距离最小”的节点(堆顶)进行扩展,节点第一次从堆中被取出时,就得到了该点的最短路。与堆优化$dijkstra$算法的流程一致,这两种做法的思想殊途同归,都是非负权图上$O(mlog\ n)$的单源最短路径算法。

例题——

poj3662 Telephone Lines

Luogu P1073 最优贸易

bzoj2200 道路与航线

任意两点间的最短路

我们可以把每个点作为起点,求解$n$次单源最短路问题。不过在任意两点间最短路问题中,图一般比较稠密。这里讲一讲$O(N^3)$的$Floyd$算法。

$Floyd$算法

咕咕咕咕

传递闭包

在交际网络中,给定若干个元素和若干对二元关系,且关系具有传递性。“通过传递性推导出尽量多的元素之间的关系”的问题被称为传递闭包。

建立临接矩阵$d$,$d[i][j]=1$表示$i$与$j$有关系,$d[i][j]=0$表示$i$与$j$没有关系,特别的,$d[i][i]$始终为1。使用$Floyd$算法可以解决传递闭包问题

 

bool d[N][N];
int n,m;
int main(){
    cin>>n>>m;
    for(int i=1;i<=n;i++) d[i][i]=1;
    for(int i=1;i<=m;i++){
        int x,y;
        cin>>x>>y;
        d[x][y]=d[y][x]=1;
    }
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                d[i][j]|=d[i][k]&d[k][j];
    return 0;
}

 

例题——

poj1094 Sorting It All Out

poj1734 Sightseeing trip

poj3613 Cow Relays

go back

 


 

二、最小生成树

昂讲一下$Kruskal$算法和$Prim$算法

$Kruskal$算法

在任意时刻,$Kruskal$算法从剩余的边中选出一条权值最小的,并且这条边的两个端点不连通,图中节点的连通情况可以用并查集维护。算法流程如下:

1.建立并查集,每个点各自构成一个集合

2.把所有边按权值从小到大排序,依次扫描每条边$(x,y,z)$

3.若$x,y$属于同一集合(连通),则忽略这条边,继续扫描下一条

4.否则,合并$x,y$所在的集合,并把$z$累加到答案中

5.所有边扫描完成后,第4步中处理过的边就构成最小生成树

时间复杂度为$O(mlog\ m)$

$Prim$算法

最初,$Prim$算法仅确定1号节点属于最小生成树。在任意时刻,设已经确定属于最小生成树的节点集合$T$,剩余节点集合为$S$。$Prim$算法找到$z$最小的边$(x,y,z)$满足$x\in T,y\in S$,然后把$y$从集合$S$中删除,加入到集合$T$,并把$z$累加到答案中。

具体来说,可以维护数组$d$:若$x\in S$,则$d[x]$表示节点$x$与集合$T$中的接地那之间权值最小边的权值。若$x\in T$,则$d[x]$表示就等于$x$被加入$T$时选出的最小边的权值。

类比$dijkstra$算法,同一个数组标记节点是否属于$T$。每次从未标记的节点中选出$d$值最小的,将其标记(新加入$T$),同时扫描所有出边,更新另一个端点的$d$值。最后,最小生成树的权值总和就是$\sum_{i=2}^{n}d[i]$

算法的时间复杂度为$O(n^2)$,可以用二叉堆优化到$O(mlog\ n)$,$Prim$算法主要用于稠密图,尤其是完全图的最小生成树的求解。

int a[N][N],d[N],n,m,ans;
bool v[N];
void prim(){
    memset(d,0x3f,sizeof(d));
    memset(v,0,sizeof(v));
    d[1]=0;
    for(int i=1;i<n;i++){
        int x=0;
        for(int j=1;j<=n;j++)
            if(!v[j]&&(x==0||d[j]<d[x])) x=j;
        v[x]=1;
        for(int j=1;j<=n;j++)
            if(!v[j]) d[j]=min(d[j],a[x][j]);
    }
}
int main(){
    cin>>n>>m;
    memset(a,0x3f,sizeof(a));
    for(int i=1;i<=n;i++) a[i][i]=0;
    for(int i=1;i<=m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        a[y][x]=a[x][y]=min(a[x][y],z);
    }
    prim();
    for(int i=2;i<=b;i++) ans+=d[i];
    cout<<ans<<endl;
    return 0;
}

例题——

TUVJ1391 走廊泼水节

poj1639 Picnic Planning

poj2728 最优比率生成树

黑暗城堡

go back

 


 

三、树的直径与最近公共祖先

 

go back

 


 

四、基环树

 

go back

 


 

五、负环与差分约束

 

go back

 


 

六、Tarjan算法与无向图连通性

无向图的割点与桥

给定无向连通图$G=(V,E)$

 

 

go back

 


 

七、Tarjan算法与有向图连通性

 

go back

 


 

八、二分图的匹配

 

go back

 


 

九、二分图的覆盖与独立集

 

go back

 


 

十、网络流初步

 

go back

posted @ 2019-02-13 21:50  小叽居biubiu  阅读(188)  评论(0编辑  收藏  举报