图论总结

最短路

1.dijkstra

要求:所有边权为正
时间复杂度:(n+m)logn

int n, m;
int dist[N];
bool st[N];

int dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, 1});
    while (heap.size())
    {
        auto t = heap.top();
        heap.pop();
        int ver = t.second, distance = t.first;
        if (st[ver]) continue;
        st[ver] = true;
        for (int i = h[ver]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (dist[j] > dist[ver] + w[i])
            {
                dist[j] = dist[ver] + w[i];
                heap.push({dist[j], j});
            }
        }
    }
    if (dist[n] == 0x3f3f3f3f) return -1;
    return dist[n];
}
2.spfa

时间复杂度:玄学复杂度,最慢可被卡到o(n*m)

int n, m;
int dist[N];
bool st[N];
int spfa()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    queue<int> q;
    q.push(1);
    st[1] = true;
    while (q.size())
    {
        int t = q.front();
        q.pop();
        st[t] = false;
        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (dist[j] > dist[t] + w[i])
            {
                dist[j] = dist[t] + w[i];
                if (!st[j])
                {
                    q.push(j);
                    st[j] = true;
                }
            }
        }
    }
    return dist[n];
}

最小生成树

1.prim算法

时间复杂度:o(n*n)

int n, m;
int g[N][N];
int dist[N];//记录未选的点到已选的集合中的点的最小距离
bool st[N];

int prim()
{
    memset(dist, 0x3f, sizeof dist);
    int res = 0;
    for (int i = 0; i < n; i ++ )
    {
        int t = -1;
        for (int j = 1; j <= n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        if (i && dist[t] == INF) return INF;
        if (i) res += dist[t];
        st[t] = true;
        for (int j = 1; j <= n; j ++ ) dist[j] = min(dist[j], g[t][j]);
    }
    return res;
}
2.Kruskal算法

时间复杂度:时间复杂度主要由排序方法决定,为o(e loge)

int n, m;
int fa[N];
struct Edge
{
    int a, b, w;
    bool operator< (const Edge &W)const
    {
        return w < W.w;
    }
}edges[M];

int find(int x)
{
    if (fa[x] != x) fa[x] = find(fa[x]);
    return fa[x];
}
int kruskal()
{
    sort(edges, edges + m);
    for (int i = 1; i <= n; i ++ ) fa[i] = i;  
    int res = 0, cnt = 0;
    for (int i = 0; i < m; i ++ )
    {
        int a = edges[i].a, b = edges[i].b, w = edges[i].w;
        a = find(a), b = find(b);
        if (a != b)
        {
            fa[a] = b;
            res += w;
            cnt ++ ;
        }
    }
    if (cnt < n - 1) return INF;
    return res;
}

targan算法:

对于每个节点定义两个数组
1.dfn[u]:节点u搜索的次序编号(时间戳)
2.low[u]:为u或u的子树能够追溯到的最早的栈中节点的次序号
其余数组
stk[N]:栈
in_stk[N]:记录点是否在栈中
sze[N]:记录强连通分量中点的数目
id[N]:点属于哪一个强连通分量
scc_cnt:强连通分量的数量

int dfn[N],low[N],timestamp;
int stk[N],top;
int in_stk[N];
int sze[N],id[N],scc_cnt;
void tarjan(int u)
{
    dfn[u] = low[u] = ++ timestamp;
    stk[ ++ top] = u, in_stk[u] = true;
    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if (!dfn[j])
        {
            tarjan(j);
            low[u] = min(low[u], low[j]);
        }
        else if (in_stk[j]) low[u] = min(low[u], dfn[j]);
    }

    if (dfn[u] == low[u])
    {
        ++ scc_cnt;
        int y;
        do {
            y = stk[top -- ];
            in_stk[y] = false;
            id[y] = scc_cnt;
            sze[scc_cnt] ++ ;
        } while (y != u);
    }
}

最近公共祖先

1.倍增求公共祖先

int depth[N],fa[N][25];
void bfs(int root)
{
    memset(depth,0x3f,sizeof depth);
    depth[0]=0;//务必不能丢
    depth[root]=1;
    queue<int>que;
    que.push(root);
    while(que.size())
    {
        int t=que.front();
        que.pop();
        for(int i=h[t];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(depth[j]>depth[t]+1)
            {
                depth[j]=depth[t]+1;
                fa[j][0]=t;
                for(int k=1;k<=20;++k)
                    fa[j][k]=fa[fa[j][k-1]][k-1];
                que.push(j);
            }
        }
    }
}
int lca(int a,int b)
{
    if(depth[a]<depth[b])swap(a,b);
    for(int i=20;i>=0;i--)
        if(depth[fa[a][i]]>=depth[b])
            a=fa[a][i];
    if(a==b)return a;
    for(int i=20;i>=0;i--)
    {
        if(fa[a][i]!=fa[b][i])
        {
            a=fa[a][i];
            b=fa[b][i];
        }
    }
    return fa[a][0];
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Matlab中,可以使用图论相关函数来进行图的分析和计算。其中一些常用的函数和方法包括: 1. 使用在线网站进行图的可视化。如果节点比较少,可以使用在线网站来进行图的可视化。这个方法适用于较小规模的图。 2. 使用矩阵表示图。在计算机中存储一个图最基本的方法就是采用矩阵来表示。图的矩阵表示根据所关心的问题不同而有邻接矩阵、关联矩阵、权矩阵等不同的方法。 3. 计算最短路径。可以使用Matlab的shortestpath函数来计算图中两个节点之间的最短路径。该函数返回图G中start节点到end节点的最短路径。 4. 计算任意两点之间的距离矩阵。可以使用Matlab的distances函数来计算图中任意两点之间的距离矩阵。该函数返回一个矩阵,其中每个元素表示两个节点之间的距离。 5. 查找给定范围内的所有点。可以使用Matlab的nearest函数来找到图中给定范围内的所有点。该函数返回一个包含所有满足条件的节点ID和距离的矩阵。 总结:在Matlab中,可以使用不同的函数和方法来进行图论分析,包括在线网站作图、使用矩阵表示图、计算最短路径、计算任意两点之间的距离矩阵以及查找给定范围内的所有点。这些方法可以帮助我们进行图的可视化、路径计算和节点分析等操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [数学建模笔记(七)图论最短路径问题学习 模型及Matlab代码](https://blog.csdn.net/weixin_47066458/article/details/119976828)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [dijkstra+Floyd图论算法的校内应急路线规划Matlab+Haskell打开方式](https://blog.csdn.net/qq_38730945/article/details/90139210)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值