acwing算法提高之图论--最小生成树的扩展应用

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

1 介绍

本专题用来记录使用最小生成树算法(prim或kruskal)解决的扩展题目。

2 训练

题目1:1146新的开始

C++代码如下,文章来源地址https://www.toymoban.com/news/detail-853624.html

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

using namespace std;

const int N = 310, INF = 0x3f3f3f3f3;
int n, m;
int g[N][N];
int d[N];
bool st[N];

void prim() {
    memset(d, 0x3f, sizeof d);
    int res = 0;
    
    for (int i = 0; i < n + 1; ++i) {
        int t = -1;
        for (int j = 0; j <= n; ++j) {
            if (!st[j] && (t == -1 || d[t] > d[j])) {
                t = j;
            }
        }
        
        st[t] = true;
        if (i) res += d[t];
        
        for (int j = 0; j <= n; ++j) {
            if (d[j] > g[t][j]) {
                d[j] = g[t][j];
            }
        }
    }
    
    cout << res << endl;
    
    return;
}

int main() {
    cin >> n;
    memset(g, 0, sizeof g);
    
    for (int i = 1; i <= n; ++i) {
        int t;
        cin >> t;
        g[0][i] = t;
        g[i][0] = t;
    }
    
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            cin >> g[i][j];
        }
    }
    
    prim();

    return 0;   
}

题目2:1145北极通讯网络

C++代码如下,

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;

typedef pair<int, int> PII;

const int N = 510, M = N * N;
int n, k;
vector<PII> points;
int p[N];

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

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

double compute_dis(int i, int j) {
    int x1 = points[i].first, y1 = points[i].second;
    int x2 = points[j].first, y2 = points[j].second;
    
    double d = double(x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
    d = sqrt(d);
    return d;
}

int main() {
    cin >> n >> k;
    for (int i = 0; i < n; ++i) {
        int x, y;
        cin >> x >> y;
        points.emplace_back(x,y);
    }
    
    for (int i = 0; i < n; ++i) p[i] = i;
    
    int m = 0;
    for (int i = 0; i < n; ++i) {
        for (int j = i + 1; j < n; ++j) {
            double w = compute_dis(i, j);
            edges[m] = {i, j, w};
            m += 1;
        }
    }
    
    sort(edges, edges + m);
    
    double res = 0.0;
    int cnt = n; //连通块的个数
    for (int i = 0; i < m; ++i) {
        int a = edges[i].a, b = edges[i].b;
        double w = edges[i].w;
        a = find(a);
        b = find(b);
        
        if (cnt == k) {
            break;
        }
        
        if (a != b) {
            p[a] = b;
            cnt--;
            res = w;
        }
    }
    
    printf("%.2lf\n", res);
    
    return 0;
}

题目3:346走廊泼水节

C++代码如下,

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

using namespace std;

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

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

int main() {
    int T;
    cin >> T;
    while (T--) {
        cin >> n;
        for (int i = 0; i < n - 1; ++i) {
            cin >> edges[i].a >> edges[i].b >> edges[i].w;
        }
        
        for (int i = 1; i <= n; ++i) p[i] = i, ms[i] = 1;
        
        sort(edges, edges + n - 1);
        
        int res = 0;
        for (int i = 0; i < n - 1; ++i) {
            int a = edges[i].a, b = edges[i].b, w = edges[i].w;
            a = find(a);
            b = find(b);
            if (a != b) {
                res += (ms[a] * ms[b] - 1) * (w + 1);
                p[a] = b;
                ms[b] += ms[a];
            }
        }
        
        cout << res << endl;
    }
    
    return 0;
}

题目4:1148秘密的牛奶运输

C++代码如下,

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

using namespace std;

typedef long long LL;

const int N = 510, M = 10010;
int n, m;
struct Edge {
    int a, b, w;
    bool f;
    bool operator< (const Edge &W) const {
        return w < W.w;
    }
}edges[M];
int p[N];
int dist1[N][N], dist2[N][N];
int h[N], e[N * 2], w[N * 2], ne[N * 2], idx;

void add(int a, int b, int c) {
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

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

void dfs(int u, int fa, int maxd1, int maxd2, int d1[], int d2[]) {
    d1[u] = maxd1, d2[u] = maxd2;
    for (int i = h[u]; ~i; i = ne[i]) {
        int j = e[i];
        if (j != fa) {
            int td1 = maxd1, td2 = maxd2;
            if (w[i] > td1) td2 = td1, td1 = w[i];
            else if (w[i] < td1 && w[i] > td2) td2 = w[i];
            dfs(j, u, td1, td2, d1, d2);
        }
    }
    return;
}

int main() {
    scanf("%d%d", &n, &m);
    memset(h, -1, sizeof h);
    for (int i = 0; i < m; ++i) {
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        edges[i] = {a, b, w};
    }
    
    sort(edges, edges + m);
    for (int i = 1; i <= n; ++i) p[i] = i;
    
    LL sum = 0;
    for (int i = 0; i < m; ++i) {
        int a = edges[i].a, b = edges[i].b, w = edges[i].w;
        int pa = find(a), pb = find(b);
        if (pa != pb) {
            p[pa] = pb;
            sum += w;
            add(a, b, w), add(b, a, w);
            edges[i].f = true;
        }
    }
    
    for (int i = 1; i <= n; ++i) dfs(i, -1, -1e9, -1e9, dist1[i], dist2[i]);
    
    LL res = 1e18;
    for (int i = 0; i < m; ++i) {
        if (!edges[i].f) {
            int a = edges[i].a, b = edges[i].b, w = edges[i].w;
            LL t;
            if (w > dist1[a][b]) {
                t = sum + w - dist1[a][b];
            } else if (w > dist2[a][b]) {
                t = sum + w - dist2[a][b];
            }
            res=  min(res, t);
        }
    }
    
    printf("%lld\n", res);
    
    return 0;
}

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

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

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

相关文章

  • 算法提高-图论-floyd算法及其扩展应用

    离散化 (只要用到200个点,但是题目给的点编号是1-1000)+ 倍增(快速幂)+ flyod变式(将递推公式改变了) 能用快速幂的原因是递推公式里面的两端路径两两之间相互独立,用结合律就可以用快速幂。矩阵乘法能用快速幂的原因也是矩阵乘法中两两矩阵之间具有结合律 帮助

    2024年02月09日
    浏览(33)
  • 算法提高-图论-单源最短路的扩展应用

    多源点单终点最短路建图: 创建虚拟源点(创建虚拟源点的时候以是spfa为例 可以在建图的时候建出来,也可以在spfa这直接入队,也是虚拟源点的意思) 反向建图变成单源点多终点,然后遍历终点的dist即可找出最短路 这题挺简单的就不详细说了,主要是第一次遇到计数问题

    2024年02月16日
    浏览(34)
  • 图论13-最小生成树-Kruskal算法+Prim算法

    基本思想:按照权值从小到大的顺序选择 n-1 条边,并保证这 n-1 条边不构成回路 具体做法:首先构造一个只含 n 个顶点的森林,然后依权值从小到大从连通网中选择边加入到森林中,并使森林中 不产生 回路,直至森林变成一棵树为止。 2.2.1 如果图不联通,直接返回空,该

    2024年02月01日
    浏览(29)
  • 【第二十三课】最小生成树:prime 和 kruskal 算法(acwing858,859 / c++代码 )

    目录 前言 Prime算法--加点法 acwing-858  代码如下 一些解释  Kruskal算法--加边法 acwing-859 并查集与克鲁斯卡尔求最小生成树  代码如下 一些解释   之前学最短路的时候,我们都是以有向图为基础的,当时我们提到如果是无向图,只要记得两个顶点处都要加边就好了。 而在最小

    2024年02月21日
    浏览(29)
  • 算法之图论

    定义 图通常以一个二元组 G=V, E表示,V表示节点集,E表示边集。节点集中元素的个数,称为图的阶。 若图G中的每条边都是没有方向的,称为无向图;每条边是由两个节点组成的无序对,例如节点V1和节点V2之间的边,记为 若图G中的每条边都是有方向的,称为有向图;有向边

    2024年02月16日
    浏览(34)
  • 图论与算法(遍历、最小生成树、最短路径)

    图是由顶点集合及顶点间的关系组成的一种数据结构: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)
  • 数据结构与算法课程设计---最小生成树的应用

    1.问题 假定有这么一个问题,有11个城市,城市之间有一些天然气管道,铺设天然气管道需要花费不同的金额,现在要你选择其中一些天然气管道,使得所有城市可以互相联通且花费最小。 2.分析 我们把这个问题抽象为一张图,每个城市是一个顶点,城市与城市之间的管道是

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

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

    2024年02月03日
    浏览(34)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包