算法提高-图论- 最小生成树

这篇具有很好参考价值的文章主要介绍了算法提高-图论- 最小生成树。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最小生成树

AcWing 1140. 最短网络

#include <iostream>
#include <cstring>

using namespace std;

const int N = 110;

int w[N][N];
int dist[N];
bool st[N];
int n;

int prime()
{
    int res = 0;
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    //和dj一样 这里1号节点虽然是最短的,但是我们需要它去更新其他边,因此不能st[1] = true;
    for (int i = 0; i < n; i ++ )//和dj一样,这里循环n次才能把n个节点加进最小生成树
    {
        int t = -1;
        
        for (int j = 1; j <= n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
                
        st[t] = true;
        res += dist[t];
        
        for (int j = 1; j <= n; j ++ )
        {
            dist[j] = min(dist[j], w[t][j]);//这里不用dist[t] + w[t][j],这是求一个点到一个集合的距离,后者是求点j到源点的距离
        }
    }
    return res;
}

int main ()
{
    cin >> n;
    for (int i = 1; i <= n; i ++ )//题目要的答案和节点的下标无关,这里能把它存下来就行了
        for (int j = 1; j <= n; j ++ )
            cin >> w[i][j];
    
    cout << prime();
    return 0;
}

AcWing 1141. 局域网

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 110, M = 210;

struct Edge
{
    int a, b, w;
    bool operator < (const Edge &t)const
    {
        return w < t.w;
    }
}e[M];

int p[N];//并查集父类数组
int n, m;

int find(int x)
{
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];//return x 也是一样的
}
int main ()
{
    cin >> n >> m;
    
    for (int i = 1; i <= n; i ++ ) p[i] = i;//并查集初始化(这个经常忘),这个下标i是有意义的,要根据题目给的节点编号来
    
    for (int i = 0; i < m; i ++ )
    {
        int a, b, w;
        cin >> a >> b >> w;
        //e[i].a = a, e[i].b = b, e[i].w = w;
        e[i] = {a, b, w};
    }
    
    sort(e, e + m);
    int res = 0;
    for (int i = 0; i < m; i ++ )
    {
        int a = find(e[i].a), b = find(e[i].b), w = e[i].w;//后面不用再find了,因为我们a,b在定义的时候就是他们所属的集合
    
        if(a != b) p[a] = b;
        else res += w;
    }
    
    cout << res;
    return 0;
}

AcWing 1142. 繁忙的都市

和上题一摸一样,但是题意要求的out看起来需要特别处理,其实只要想清楚kruskal的性质就好

//kruskal本身就具有选择的路的权值中最大的权值尽量小这个性质,因为我们边是排序了的
#include <iostream>
#include <algorithm>

using namespace std;

const int N = 310, M = 8010;

struct Edge
{
    int a, b, w;
    bool operator < (struct Edge &t)
    {
        return w < t.w;
    }
}e[M];

int n, m;
int p[N];

int find (int x)
{
    if (p[x] != x) p[x] = find (p[x]);
    return p[x];
}

int main ()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ ) p[i] = i;
    
    for (int i = 0; i < m; i ++ )
    {
        int a, b, w;
        cin >> a >> b >> w;
        e[i] = {a, b, w};
    }
    
    sort(e, e + m);
    int cnt = 0, res = 0;
    for (int i = 0; i < m; i ++ )
    {
        int a = find(e[i].a), b = find(e[i].b), w = e[i].w;
        
        if (a != b) 
        {
            p[a] = b;
            cnt ++ ;
            res = w;
        }
    }
    
    cout << cnt << " " << res ;
    return 0;
}

AcWing 1143. 联络员

//1.用到了缩点,但本题的是无形中的,一个联通块的缩成了它的父节点
//2.知道了kurskal有多牛,可以解决已经有一些边的最小生成树问题,也可以解决只找一部分边的最小生成树的问题
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 2010, M = 10010;

struct Edge
{
    int a, b, w;
    bool operator < (struct Edge & t)
    {
        return w < t.w;
    }
}e[M];

int p[N];
int n, m;

int find (int x)
{
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}
int main ()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i ++ ) p[i] = i;
    
    int res = 0, k = 0;
    
    for (int i = 0; i < m; i ++ ) 
    {
        int t, a, b, w;
        cin >> t >> a >> b >> w;
        if (t == 1)
        {
            p[find(a)] = find(b);//先建立必须要选择的边
            res += w;
        }
        else 
        {
            e[k ++ ] = {a, b, w};//不是必须要选择的再加入e数组
        }
    }
    
    sort(e, e + k);
    for (int i = 0; i < k; i ++ )
    {
        int a = find(e[i].a), b = find(e[i].b), w = e[i].w;
        if (a != b)
        {
            p[a] = b;
            res += w;
        }
    }
    cout << res;
    return 0;
}

AcWing 1144. 连接格点

题意就是求最小生成树,因为边权都是正数,那么我们多选一条边必然会导致我们的代价增大
但如果题目说了边权为正或者负数,那么就不是最小生成树了,极端一点所有边都是负的,那么我们为了代价最小肯定是所有边都选文章来源地址https://www.toymoban.com/news/detail-596764.html

//有点类似于拯救大兵那题
#include <iostream>
#include <cstring>

using namespace std;

const int N = 1e3 + 10, M = N * N, K = 2 * N * N;//M:点数, K = 边数

struct  Edge
{
    int a, b, w;
}e[K];
int p[M];
int ids[N][N], cnt;//将二维坐标映射成1维
int n, m, k;

int find(int x)
{
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

void get_edges()
{
    int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, -1, 0, 1}, dw[4] = {1, 2, 1, 2};//必须要按1212的顺序枚举,这样u%2的时候就可以先添加1的边再添加2的边,自己排序少一个快排logn的复杂度
    for (int z = 0; z < 2; z ++ )//先枚举u%2余数为0的再枚举u%2余数为1的,余数为0说明是竖边权值为1,为1说明是横边权值为2
        for (int i = 1; i <= n; i ++ )
            for (int j = 1; j <= m; j ++ )
                for (int u = 0; u < 4; u ++ )
                {
                    if (u % 2 == z)
                    {
                        int x = i + dx[u], y = j + dy[u], w = dw[u];
                        int a = ids[i][j], b = ids[x][y];
                        if (a < b) e[k ++ ] = {a, b, w};//因为是无向边我们枚举一个就行了
                    }
                }
}
int main()
{
    cin >> n >> m;
    
    for (int i = 1; i <= n * m; i ++ ) p[i] = i;
    
    for (int i = 1;i <= n; i ++ )//将二维坐标映射成1维
        for (int j = 1; j <= m; j ++ )
            ids[i][j] = ++ cnt;
    
    int x1, x2, y1, y2;
    while(cin >> x1 >> y1 >> x2 >> y2)
    {
        int a = ids[x1][y1], b = ids[x2][y2];
        p[find(a)] = find(b);
    }
    
    get_edges();//初始化e[]
    
    
    int res = 0;
    for (int i = 0; i < k; i ++ )
    {
        int a = find(e[i].a), b = find(e[i].b), w = e[i].w;
        if (a != b)
        {
            p[a] = b;
            res += w;
        }
    }
    
    cout << res;
    
    return 0;
    
}

到了这里,关于算法提高-图论- 最小生成树的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 图论与算法(遍历、最小生成树、最短路径)

    图是由顶点集合及顶点间的关系组成的一种数据结构:G = (V, E),其中:顶点集合V = {x|x属于某个数据对象集}是有穷非空集合;E = {(x,y)|x,y属于V}或者E = {x, y|x,y属于V Path(x, y)}是顶点间关系的有穷集合,也叫做边的集合。(x, y)表示x到y的一条双向通路,即(x, y)是无方向的;Path

    2024年04月14日
    浏览(30)
  • 【算法每日一练]-图论(保姆级教程篇7 最小生成树 ,并查集模板篇)#村村通 #最小生成树

    目录 题目:村村通 并查集  题目:最小生成树 kruskal算法 prim算法          先引入问题: 要在n个城市之间铺设光缆,主要目标是要使这 n 个城市的 任意两个之间都可以通信 ,但铺设光缆的费用很高,且各个城市之间铺设光缆的费用不同,因此另一个目标是要 使铺设光

    2024年02月04日
    浏览(62)
  • 【算法基础:搜索与图论】3.5 求最小生成树算法(Prim&Kruskal)

    最小生成树 有关树的定义 生成子图 :生成子图是从原图中选取部分节点以及这些节点之间的边所组成的图。生成子图中的所有节点和边都必须在原图中存在。 生成树 :一个连通 无向图 的 生成子图 ,同时要求是树。也即在图的边集中选择 n - 1 条,将所有顶点连通。 我们

    2024年02月16日
    浏览(28)
  • 【算法入门&图论】【模板】拓扑排序|【模板】单源最短路2 |最小生成树

    ✅作者简介:热爱后端语言的大学生,CSDN内容合伙人 ✨精品专栏:C++面向对象 🔥系列专栏:算法百炼成神 本专栏收录的均为牛客网的算法题目,内含链表、双指针、递归、动态规划、基本数据结构等算法思想的具体运用。牛客网不仅有大量的经典算法题目,也有大厂的面

    2024年02月03日
    浏览(34)
  • 数学建模十大算法04—图论算法(最短路径、最小生成树、最大流问题、二分图)

    一、最短路径问题 从图中的某个顶点出发,到达另一个顶点的 所经过的边的权重之和最小 的一条路径。 1.1 两个指定顶点之间的最短路径 问题如下:给出了一个连接若干个城镇的铁路网络,在这个网络的两个指定城镇间,求一条最短铁路线。 1.1.1 Dijkstra算法 迪杰斯特拉(D

    2024年02月02日
    浏览(47)
  • 【算法导论】图论(图的基本概念,图上的深度优先搜索(DFS),广度优先搜索(BFS),最小生成树(MST)及Prim,Kruskal算法)

    图(Graph)是一种包含节点与节点的边的集合,记作G=(V,E),V是节点的集合,E是边的集合。 有向图 一个有向图G=(V,E),E中每个元素是V上的一个二值关系:一条从a出发的连向b的边e可以记作一个 有序 对e = (a,b) 。 无向图 一个无向图G=(V,E),E的每个元素e可以表示V上的一个 无序 对,记

    2024年02月03日
    浏览(32)
  • 图论- 最小生成树

    一幅图可以有很多不同的生成树,比如下面这幅图,红色的边就组成了两棵不同的生成树: 对于加权图, 每条边都有权重(用最小生成树算法的现实场景中,图的边权重一般代表成本、距离这样的标量),所以每棵生成树都有一个权重和。 比如上图,右侧生成树的权重和显

    2024年04月25日
    浏览(24)
  • 图论——最小生成树

    想了解最小生成树,首先得明白什么是生成树。 生成树的概念: 包含连通图中所有的顶点,且任意两顶点之间有且仅有一条通路。 那什么是最小生成树? 最小生成树(Minimum Spanning Trees)的概念:连通图的一颗生成树(Spanning Tree)是包含图的所有顶点的连通无环子图(也就是一棵

    2023年04月13日
    浏览(24)
  • 【图论】最小生成树的应用

    P1550 [USACO08OCT] Watering Hole G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 1.我们是要使所有的农场都要有水 2.可以从起点引水,也可以互相引水。 3.费用要最小 这时我们可以想到最小生成树,建立一个虚拟节点即可。思路一目了然。 当看到这些条件,可以想到最小生成树 1.涉及

    2024年02月10日
    浏览(25)
  • 【图论】最小生成树(python和cpp)

    本帖持续更新中 如有纰漏望指正! (a)点云建立的k近邻图 (b)k近邻图上建立的最小生成树 最小生成树 (Minimum Spanning Tree,简称 MST) 是一种在带权无向图中的树,它连接了图中所有节点并且总权重最小。在最小生成树中,任意两个节点之间有且仅有一条路径,同时这些路径

    2024年02月05日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包