跳过正文
  1. 学习笔记/
  2. Language/
  3. C++ Algorithm/
  4. C++ · 基础算法/

·1 分钟·
lyrumu
作者
lyrumu
目录

图论基础
#


图的存储
#


邻接表存图
#

对于每一个节点,记录这个几点连接的所有其他节点和对应权值

 1#include <bits/stdc++.h>
 2using namespace std;
 3const int N = 100010;
 4vector<pair<ll,int> graph[N];//图,{权值,对应的节点}
 5int n,m;
 6int main(){
 7    cin>>n>>m;
 8    for(int i = 0;i<m;i++){
 9        int u,v,w;
10        cin>>u>>v>>w;
11        graph[u].push_back({w,v});
12        graph[v].push_back({w,u});
13    }
14}

邻接矩阵存图
#

用一个二维数组记录每两个点之间的距离

两个索引分别代表两个点 g[i][j]的值代表点i和j之间的距离

 1#define ll long long
 2const int N = 200010;
 3const ll INF = 4e18;
 4ll g[N][N];
 5int main(){
 6    int n,m;
 7    cin>>n>>m;
 8    for(int i = 1;i<=n;i++){
 9        for(int j = 1;j<=n;j++){
10            if(i==j){
11                g[i][j] = 0;//同一个点当然是0
12            }else{
13                g[i][j] = INF;//初始化矩阵为INF(不可达)
14            }
15        }
16    }
17    for(int i = 0;i<m;i++){
18        int u,v;
19        ll w;
20        cin>>u>>v>>w;
21        //无向图
22        g[u][v] = min(g[u][v],w);
23        g[v][u] = min(g[v][u],w);//注意 这里出现重边时取用min是绝大部分情况 不排除其他写法
24        //如果是有向图,只用下面这一行
25        //g[u][v] = min(g[u][v],w);
26    }
27}

稠密图&稀疏图
#

令n=点数 m=边数

因此无向图最大边数=(n*(n-1))/2

如果m接近于这个最大边数 就是稠密图

如果m接近n或者更小 就是稀疏图

可以根据稀疏和稠密的性质选择算法 获得更高效率


最小生成树
#

复杂度

  • Prim–>O(n^2)

  • Prim堆优化–>O(m log n)

  • Kruskal–>O(m log m)

一般来说

  • 稠密图->朴素Prim

  • 稀疏图->Kruskal或者堆优化Prim

另外:

  • 如果n与m很接近(n==m)

选择Kruskal和堆优化Prim在复杂度上没有差异

但是Kruskal是基于sort排序和并查集 更快且不容易写错

选择Kruskal